欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#编码规范

程序员文章站 2023-08-25 14:03:06
记录 编码约定 学习过程。 命名空间约定 如果没有使用using指令,项目也没有默认导入合适的命名空间,访问这些命名空间或者类型时,则需要“完全限定名称”。 namespace ConsoleApp4 { class Program { static void Main(string[] args) ......

记录 学习过程。

 

命名空间约定

如果没有使用using指令,项目也没有默认导入合适的命名空间,访问这些命名空间或者类型时,则需要“完全限定名称”。

namespace consoleapp4
{
    class program
    {
        static void main(string[] args) 
        {
            // 在这里system.diagnostics是“完全限定名称”
            var tracesource = new system.diagnostics.tracesource("");
        }
    }
}

如果使用了using指令,则不需要“完全限定名称”。

using system.diagnostics;

namespace consoleapp4
{
    class program
    {
        static void main(string[] args)
        {            
            var tracesource = new tracesource("");
        }
    }  
}

 

代码布局约定

  1. 不轻易更改编辑器的设置,通常使用默认的,特别是格式设置和制表符。
    C#编码规范
  2. 每行一条语句,每行一个声明。
    string[] strs = new string[] { "aa","bb","cc"};
    string str = "hello";
    int num = 4;
    if (num == 9)
    {
    
    }
  3. 一行写不完的语句,断行写则需要缩进一个制表符位,除了起头的第一行,后面无论再断多少行都是一个制表符位。
    string[] strs = new string[] { "aa","bb","cc"};            
    var query = strs.where(x => x.length == 2 && x.contains("b")).
        select(x => new { name = x, age = 8 });
  4. 属性和方法之间至少一个空行
    public int myproperty { get; set; }
    public int myproperty1 { get; set; }
    
    void test()
    {
    
    }
  5. 使用括号突出表达式的字句。
    int val1 = 1;
    int val2 = 3;
    int val3 = 4;
    
    if ((val1 > val2) && (val1 > val3))
    {
        
    }
    

注释约定

单独的行,而非代码末尾;大写字母开头,断行换小写;句点结束注释文本;注释和文本之间留一个空格。

不要在注释周围创建格式化的星号块???没看懂。

下面放一段ilspy源码

/// <summary>
/// sets the value of a dependency property on <paramref name="targetobject"/> using a markup extension.
/// </summary>
/// <remarks>this method does not support markup extensions like x:static that depend on
/// having a xaml file as context.</remarks>
public static void setvaluetoextension(this dependencyobject targetobject, dependencyproperty property, markupextension markupextension)
{
    // this method was copied from icsharpcode.core.presentation (with permission to switch license to x11)
    
    if (targetobject == null)
        throw new argumentnullexception(nameof(targetobject));
    if (property == null)
        throw new argumentnullexception(nameof(property));
    if (markupextension == null)
        throw new argumentnullexception(nameof(markupextension));
    
    var serviceprovider = new setvaluetoextensionserviceprovider(targetobject, property);
    targetobject.setvalue(property, markupextension.providevalue(serviceprovider));
}

 

隐式类型var

当明显可以从赋值右侧推导左侧变量类型时,使用var。当精确的类型不太重要时,使用var。

var var1 = "this is clearly a string.";
var var2 = 27;
var var3 = convert.toint32(console.readline());

右侧类型不明确时,则可以声明一个明确的类型。

using system;

namespace consoleapp4
{
    class program
    {
        static void main(string[] args)
        {
            string test = getobject(2);
            int test1 = getobject(1);
            decimal test2 = getobject(3);
        }

        static dynamic getobject(int x)
        {
            switch (x)
            {
                case 1:return 2;
                case 2:return "";
                default:return 8m;
            }
        }
    }   
}

在for循环使用var,下面的i分别推导为int、decimal。

for (var i = 0; i < 10000; i++)
{               
}

for(var i = 0m; i < 10m; i = i + 0.1m)
{
}

在foreach中不建议使用var。

datatable datatable = new datatable();
// 枚举值:enumerablerowcollection<datarow>,可以推row为datarow。
foreach (var row in datatable.asenumerable())
{

}
// 虽然可以推,但声明明确的类型会让代码更加清晰,因为无法在枚举泛型类型里明显看出当前row的类型。
foreach (datarow row in datatable.asenumerable())
{

}
// 枚举值:datarowcollection,不声明明确类型row则为object?,因此需要声明明确的类型。
foreach (datarow row in datatable.rows)
{

}

符号类型

使用时,符号类型优先于无符号类型。short、int、long。 ushort、uint、ulong。

数组

使用间接的语法声明数组

// 这时候,无法从右侧推导变量类型。
string[] vowels1 = { "a", "e", "i", "o", "u" };

// 可以推导,左侧使用var
var vowels2 = new string[] { "a", "e", "i", "o", "u" };

var vowels3 = new string[2];
vowels3[0] = "a";
vowels3[1] = "e";

委托

使用简短的语法为委托赋值。

static void main(string[] args)
{            
    del exampledel2 = delmethod;
    var del3 = new del(delmethod);
}

public delegate void del(string message);

public static void delmethod(string str)
{
    console.writeline("delmethod argument: {0}", str);
}

using

如果使用try...finally...,且在finally只有释放资源的代码,考虑替换成using,using会自动调用dispose方法。

font font1 = new font("arial", 10.0f);
try
{

}
finally
{
    font1.dispose();
}

using(font font=new font("arial", 10.0f))
{

}

new运算符

能推导类型使用var,对象实例的构造函数没有参数则不必调用构造函数。

// 不必使用new exampleclass()
var instance3 = new exampleclass
{
    name = "desktop",
    id = 37414,
    location = "redmond",
    age = 2.3
};

var instance4 = new exampleclass();
instance4.name = "desktop";
instance4.id = 37414;
instance4.location = "redmond";
instance4.age = 2.3;

事件处理

在事件比较简短、且只使用一次的情况下,可以考虑使用lambda表达式。

public form1()
{
    initializecomponent();
    
    this.click += (s, e) =>
    {
        messagebox.show(s.tostring());
    };
}

 静态成员

 派生对象时,不建议添加和基类具有相同名称的静态成员。

using system;

namespace consoleapp4
{
    class program
    {
        static void main(string[] args)
        {
            exampleclass2.test();
        }      
    }

    class exampleclass
    {
        public static void test()
        {
            console.writeline("调用exampleclass test");
        }
    }
    class exampleclass2:exampleclass
    {
        // 同名容易引起混乱,隐性覆盖了exampleclass的test方法。
        public static void test()
        {
            console.writeline("调用exampleclass2 test");
        }        
    }

    class exampleclass3 : exampleclass
    {
        // 使用new,说明有意覆盖。
        public new static void test()
        {

        }
    }
}

 linq查询表达式

 匿名类型遵循pascal大小写格式(与骆驼命名法类似,骆驼命名法是首字母小写,而pascal帕斯卡命名法是首字母大写)。

var localdistributors = from customer in customers
                        join distributor in distributors on customer.city equals distributor.city
                        select new
                        {
                            customer = customer,
                            distributor = distributor,
                            custometorid = customer.id
                        };

在查询变量和范围变量的声明中使用隐式类型化,虽然查询变量没有明确标有var关键字,但确实隐式化了。

using system;
using system.linq;

namespace consoleapp4
{
    class program
    {
        static void main(string[] args)
        {
            var customers = new system.collections.generic.list<customer>();
            var distributors = new system.collections.generic.list<distributor>();

            var localdistributors = from customer in customers
                                    join distributor in distributors on customer.city equals distributor.city
                                    select new
                                    {
                                        customer = customer,
                                        distributor = distributor,
                                        custometorid = customer.id
                                    };

        }
    }

    internal class distributor
    {
        public object city { get; internal set; }
    }
    internal class customer
    {
        public object city { get; internal set; }
        public object id { get; internal set; }
    }
}

对其from字句下面的查询语句。

// 第一种:from语句不和声明变量同一行,则在下一行缩进一个制表符。
var localdistributors = from customer in customers join distributor in distributors on customer.city equals distributor.city select new { customer = customer, distributor = distributor, custometorid = customer.id };
// 第二种:from语句和声明变量同一行 var localdistributors = from customer in customers join distributor in distributors on customer.city equals distributor.city select new { customer = customer, distributor = distributor, custometorid = customer.id };