解析C#编程的通用结构和程序书写格式规范

C# 程序的通用结构
C# 程序可由一个或多个文件组成。每个文件都可以包含零个或零个以上的命名空间。一个命名空间除了可包含其他命名空间外,还可包含类、结构、接口、枚举、委托等类型。以下是 C# 程序的主干,它包含所有这些元素。

// A skeleton of a C# program
using System;
namespace YourNamespace
{
  class YourClass
  {
  }

  struct YourStruct
  {
  }

  interface IYourInterface
  {
  }

  delegate int YourDelegate();

  enum YourEnum
  {
  }

  namespace YourNestedNamespace
  {
    struct YourStruct
    {
    }
  }

  class YourMainClass
  {
    static void Main(string[] args)
    {
      //Your program starts here...
    }
  }
}

C# 编码约定

C# 语言规范 未定义编码标准。但是,Microsoft 根据本主题中的准则来开发样本和文档。
编码约定可实现以下目的:

  • 它们为代码创建一致的外观,以确保读取器专注于内容而非布局。
  • 它们使得读取器可以通过基于之前的经验进行的假设更快地理解代码。
  • 它们便于复制、更改和维护代码。
  • 它们展示 C# 最佳做法。

命名约定

在不包括 using 指令的短示例中,使用命名空间限定。如果你知道命名空间默认导入项目中,则不必完全限定来自该命名空间的名称。如果对于单行来说过长,则可以在点 (.) 后中断限定名称,如下面的示例所示。

var currentPerformanceCounterCategory = new System.Diagnostics.
  PerformanceCounterCategory();

你不必更改通过使用 Visual Studio 设计器工具创建的对象的名称以使它们适合其他准则。
布局约定
好的布局利用格式设置来强调代码的结构并使代码更便于阅读。Microsoft 示例和样本符合以下约定:

  • 使用默认的代码编辑器设置(智能缩进、4 字符缩进、制表符保存为空格)。有关详细信息,请参阅选项、文本编辑器、C#、格式设置。
  • 每行只写一条语句。
  • 每行只写一个声明。
  • 如果连续行未自动缩进,请将它们缩进一个制表符位(四个空格)。
  • 在方法定义与属性定义之间添加至少一个空白行。

使用括号突出表达式中的子句,如下面的代码所示。

if ((val1 > val2) && (val1 > val3))
{
  // Take appropriate action.
}

注释约定
将注释放在单独的行上,而非代码行的末尾。
以大写字母开始注释文本。
以句点结束注释文本。
在注释分隔符 (//) 与注释文本之间插入一个空格,如下面的示例所示。

// The following declaration creates a query. It does not run
// the query.

不要在注释周围创建格式化的星号块。
语言准则
以下各节介绍 C# 遵循以准备代码示例和样本的做法。
String 数据类型
使用 + 运算符来连接短字符串,如下面的代码所示。

string displayName = nameList[n].LastName + ", " + nameList[n].FirstName;
若要在循环中追加字符串,尤其是在使用大量文本时,请使用 StringBuilder 对象。

var phrase = "lalalalalalalalalalalalalalalalalalalalalalalalalalalalalala";
var manyPhrases = new StringBuilder();
for (var i = 0; i < 10000; i++)
{
  manyPhrases.Append(phrase);
}
//Console.WriteLine("tra" + manyPhrases);

隐式类型的局部变量
当变量类型明显来自赋值的右侧时,或者当精度类型不重要时,请对本地变量进行隐式类型化。

// When the type of a variable is clear from the context, use var
// in the declaration.
var var1 = "This is clearly a string.";
var var2 = 27;
var var3 = Convert.ToInt32(Console.ReadLine());

当类型并非明显来自赋值的右侧时,请勿使用 var。

// When the type of a variable is not clear from the context, use an
// explicit type.
int var4 = ExampleClass.ResultSoFar();

请勿依靠变量名称来指定变量的类型。它可能不正确。

// Naming the following variable inputInt is misleading.
// It is a string.
var inputInt = Console.ReadLine();
Console.WriteLine(inputInt);

避免使用 var 来代替 dynamic。
使用隐式类型化来确定 for 和 foreach 循环中循环变量的类型。
下面的示例在 for 语句中使用隐式类型化。

var syllable = "ha";
var laugh = "";
for (var i = 0; i < 10; i++)
{
  laugh += syllable;
  Console.WriteLine(laugh);
}

下面的示例在 foreach 语句中使用隐式类型化。

foreach (var ch in laugh)
{
  if (ch == 'h')
    Console.Write("H");
  else
    Console.Write(ch);
}
Console.WriteLine();

无符号数据类型
通常,使用 int 而非无符号类型。 int 的使用在整个 C# 中都很常见,并且当你使用 int 时,更易于与其他库交互。
数组
当在声明行上初始化数组时,请使用简洁的语法。

// Preferred syntax. Note that you cannot use var here instead of string[].
string[] vowels1 = { "a", "e", "i", "o", "u" };

// If you use explicit instantiation, you can use var.
var vowels2 = new string[] { "a", "e", "i", "o", "u" };

// If you specify an array size, you must initialize the elements one at a time.
var vowels3 = new string[5];
vowels3[0] = "a";
vowels3[1] = "e";
// And so on.

委托
使用简洁的语法来创建委托类型的实例。

 // First, in class Program, define the delegate type and a method that
// has a matching signature.

// Define the type.
public delegate void Del(string message);

// Define a method that has a matching signature.
public static void DelMethod(string str)
{
  Console.WriteLine("DelMethod argument: {0}", str);
}

 // In the Main method, create an instance of Del.

// Preferred: Create an instance of Del by using condensed syntax.
Del exampleDel2 = DelMethod;

// The following declaration uses the full syntax.
Del exampleDel1 = new Del(DelMethod);

异常处理中的 try-catch 和 using 语句
对大多数异常处理使用 try-catch 语句。

static string GetValueFromArray(string[] array, int index)
{
  try
  {
    return array[index];
  }
  catch (System.IndexOutOfRangeException ex)
  {
    Console.WriteLine("Index is out of range: {0}", index);
    throw;
  }
}

通过使用 C# using 语句简化你的代码。如果你具有 try-finally 语句(该语句中 finally 块的唯一代码是对 Dispose 方法的调用),请使用 using 语句代替。

// This try-finally statement only calls Dispose in the finally block.
Font font1 = new Font("Arial", 10.0f);
try
{
  byte charset = font1.GdiCharSet;
}
finally
{
  if (font1 != null)
  {
    ((IDisposable)font1).Dispose();
  }
}

// You can do the same thing with a using statement.
using (Font font2 = new Font("Arial", 10.0f))
{
  byte charset = font2.GdiCharSet;
}

&& 和 || 运算符
若要通过跳过必要的比较来避免异常和提高性能,请在执行比较时使用 && 来代替 &,使用 || 来代替 | ,如下面的示例所示。

Console.Write("Enter a dividend: ");
var dividend = Convert.ToInt32(Console.ReadLine());

Console.Write("Enter a divisor: ");
var divisor = Convert.ToInt32(Console.ReadLine());

// If the divisor is 0, the second clause in the following condition
// causes a run-time error. The && operator short circuits when the
// first expression is false. That is, it does not evaluate the
// second expression. The & operator evaluates both, and causes
// a run-time error when divisor is 0.
if ((divisor != 0) && (dividend / divisor > 0))
{
  Console.WriteLine("Quotient: {0}", dividend / divisor);
}
else
{
  Console.WriteLine("Attempted division by 0 ends up here.");
}

New 运算符
隐式类型化时,请使用对象实例化的简洁形式,如下面的声明所示。

var instance1 = new ExampleClass();

上一行等同于下面的声明。

ExampleClass instance2 = new ExampleClass();

使用对象初始值设定项来简化对象创建。

// Object initializer.
var instance3 = new ExampleClass { Name = "Desktop", ID = 37414,
  Location = "Redmond", Age = 2.3 };

// Default constructor and assignment statements.
var instance4 = new ExampleClass();
instance4.Name = "Desktop";
instance4.ID = 37414;
instance4.Location = "Redmond";
instance4.Age = 2.3;

事件处理
如果你正定义一个稍后不需要删除的事件处理程序,请使用 lambda 表达式。

 public Form2()
{
  // You can use a lambda expression to define an event handler.
  this.Click += (s, e) =>
    {
      MessageBox.Show(
        ((MouseEventArgs)e).Location.ToString());
    };
}

 // Using a lambda expression shortens the following traditional definition.
public Form1()
{
  this.Click += new EventHandler(Form1_Click);
}

void Form1_Click(object sender, EventArgs e)
{
  MessageBox.Show(((MouseEventArgs)e).Location.ToString());
}

静态成员
通过使用类名称调用静态成员:ClassName.StaticMember。这种做法通过明确静态访问使代码更易于阅读。请勿使用派生类的名称限定基类中定义的静态成员。编译该代码时,代码可读性具有误导性,如果向派生类添加具有相同名称的静态成员,代码可能会被破坏。
LINQ 查询
对查询变量使用有意义的名称。下面的示例为位于西雅图的客户使用 seattleCustomers。

var seattleCustomers = from cust in customers
            where cust.City == "Seattle"
            select cust.Name;

使用别名确保匿名类型的属性名称都使用 Pascal 大小写格式正确大写。

var localDistributors =
  from customer in customers
  join distributor in distributors on customer.City equals distributor.City
  select new { Customer = customer, Distributor = distributor };

如果结果中的属性名称模棱两可,请对属性重命名。例如,如果你的查询返回客户名称和分销商 ID,而不是在结果中将它们保留为 Name 和 ID,请对它们进行重命名以明确 Name 是客户的名称,ID 是分销商的 ID。

var localDistributors2 =
  from cust in customers
  join dist in distributors on cust.City equals dist.City
  select new { CustomerName = cust.Name, DistributorID = dist.ID };

在查询变量和范围变量的声明中使用隐式类型化。

var seattleCustomers = from cust in customers
            where cust.City == "Seattle"
            select cust.Name;

对齐 from 子句下的查询子句,如上面的示例所示。
在其他查询子句之前使用 where 子句,以确保后面的查询子句作用于经过减少和筛选的数据集。

var seattleCustomers2 = from cust in customers
            where cust.City == "Seattle"
            orderby cust.Name
            select cust;

使用多行 from 子句代替 join 子句以访问内部集合。例如,Student 对象的集合可能包含测验分数的集合。当执行以下查询时,它返回高于 90 的分数,并返回得到该分数的学生的姓氏。

// Use a compound from to access the inner sequence within each element.
var scoreQuery = from student in students
         from score in student.Scores
         where score > 90
         select new { Last = student.LastName, score };
(0)

相关推荐

  • C#中调用Windows API的技术要点说明

    在.Net Framework SDK文档中,关于调用Windows API的指示比较零散,并且其中稍全面一点的是针对Visual Basic .net讲述的.本文将C#中调用API的要点汇集如下,希望给未在C#中使用过API的朋友一点帮助.另外如果安装了Visual Studio .net的话,在C:\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Samples\Technologies\Interop\PlatformInvo

  • 全面解读C#编程中的析构函数用法

    析构函数用于析构类的实例. 备注 不能在结构中定义析构函数.只能对类使用析构函数. 一个类只能有一个析构函数. 无法继承或重载析构函数. 无法调用析构函数.它们是被自动调用的. 析构函数既没有修饰符,也没有参数. 例如,下面是类 Car 的析构函数的声明: class Car { ~Car() // destructor { // cleanup statements... } } 该析构函数隐式地对对象的基类调用 Finalize.这样,前面的析构函数代码被隐式地转换为以下代码: protec

  • C#提高编程能力的50个要点总结

    本文总结了C#提高编程能力的50个要点.分享给大家供大家参考,具体如下: 1.总是用属性 (Property) 来代替可访问的数据成员 2.在  readonly 和 const 之间,优先使用 readonly 3.在 as 和 强制类型转换之间,优先使用 as 操作符 4.使用条件属性 (Conditional Attributes) 来代替条件编译语句 #if 5.总是为自定义类重载 ToString 方法 6.区别值类型和引用类型 7.使用不可变的值类型(Immutable Atomic

  • C#日期格式化的几个要点小结

    日期格式化 标准 DateTime 格式字符串 如果格式字符串只包含下表列出的某个单个格式说明符,则它们被解释为标准格式说明符.如果指定的格式字符是单个字符并且不包含在下表中,则引发异常.如果格式字符串在长度上比单个字符长(即使多余的字符是空白),则格式字符串被解释为自定义格式字符串.请注意,这些格式说明符产生的模式受"区域选项"控制面板中的设置的影响.具有不同区域性或不同日期与时间设置的计算机将显示不同的模式. 格式字符串显示的时间和日期分隔符由与当前区域性的 DateTimeFor

  • 详解C#面相对象编程中的继承特性

    继承(加上封装和多态性)是面向对象的编程的三个主要特性(也称为"支柱")之一. 继承用于创建可重用.扩展和修改在其他类中定义的行为的新类.其成员被继承的类称为"基类",继承这些成员的类称为"派生类".派生类只能有一个直接基类.但是,继承是可传递的.如果 ClassB 派生出 ClassC,ClassA 派生出 ClassB,则 ClassC 会继承 ClassB 和 ClassA 中声明的成员. 注意 结构不支持继承,但可以实现接口. 从概念上来

  • 讲解C#面相对象编程中的类与对象的特性与概念

    类 "类"是一种构造,通过使用该构造,您可以将其他类型的变量.方法和事件组合在一起,从而创建自己的自定义类型.类就像一个蓝图,它定义类型的数据和行为.如果类没有声明为静态类,客户端代码就可以创建赋给变量的"对象"或"实例",从而使用该类.在对变量的所有引用都超出范围之前,该变量始终保持在内存中.所有引用都超出范围时,CLR 将标记该变量以供垃圾回收.如果类声明为静态类,则内存中只存在一个副本,并且客户端代码只能通过该类自身而不是"实例变

  • 详解C#编程中构造函数的使用

    当类或结构创建时,其构造函数调用.构造函数与选件类或结构相同,并且,它们通常用于初始化新对象的数据成员. 在下面的示例中,使用一个简单的构造函数定义了名为 Taxi 的类.然后使用 new 运算符来实例化该类.在为新对象分配内存之后,new 运算符立即调用 Taxi 构造函数. public class Taxi { public bool isInitialized; public Taxi() { isInitialized = true; } } class TestTaxi { stat

  • C#编程中枚举类型的使用教程

    枚举类型(也称为枚举)为定义一组可以赋给变量的命名整数常量提供了一种有效的方法.例如,假设您必须定义一个变量,该变量的值表示一周中的一天.该变量只能存储七个有意义的值.若要定义这些值,可以使用枚举类型.枚举类型是使用 enum关键字声明的. enum Days { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }; enum Months : byte { Jan, Feb, Mar, Apr, May, Jun,

  • 解析C#编程的通用结构和程序书写格式规范

    C# 程序的通用结构 C# 程序可由一个或多个文件组成.每个文件都可以包含零个或零个以上的命名空间.一个命名空间除了可包含其他命名空间外,还可包含类.结构.接口.枚举.委托等类型.以下是 C# 程序的主干,它包含所有这些元素. // A skeleton of a C# program using System; namespace YourNamespace { class YourClass { } struct YourStruct { } interface IYourInterface

  • Netty实战源码解析NIO编程

    目录 1 前言 2 Netty是什么? 3 Java I/O模型简介 3.1 BIO代码实现 4 Java NIO 4.1 基本介绍 4.2 三大核心组件的关系 4.3 Buffer缓冲区 4.4 Channel通道 4.5 Selector选择器 4.5.1 Selector的创建 4.5.2 注册Channel到Selector 4.5.3 SelectionKey 4.5.4 从Selector中选择Channel 4.5.5 停止选择的方法 4.5.6 NIO客户端.服务端 5 Java

  • Android编程实现监控各个程序流量的方法

    本文实例讲述了Android编程实现监控各个程序流量的方法.分享给大家供大家参考,具体如下: public void getAppTrafficList(){ //获取所有的安装在手机上的应用软件的信息,并且获取这些软件里面的权限信息 PackageManager pm=getPackageManager();//获取系统应用包管理 //获取每个包内的androidmanifest.xml信息,它的权限等等 List<PackageInfo> pinfos=pm.getInstalledPac

  • Android编程获取APP应用程序基本信息辅助类【APP名称、包名、图标,版本号等】

    本文实例讲述了Android编程获取APP应用程序基本信息辅助类.分享给大家供大家参考,具体如下: 经常会用到 获取App信息,可以用这个工具类,可以获得 APP的应用程序名称.包名.图标,版本号基本信息 //跟App相关的辅助类 public class AppUtils { /** * 获取应用程序名称 */ public static synchronized String getAppName(Context context) { try { PackageManager package

  • 易语言编程入门第一个程序

    目录 易语言的优点: 最早接触易语言是三年前的事情了,那时候是因为DNF这个游戏我才知道了易语言这个编程语言,当时对他就非常的憧憬.只不过那时候易语言的学习资源比较少,而且自身的学业比较重就没有仔细的了解了. 最近几日再回归DNF的时候突然想到了易语言,所以决定抽点空闲时间学习一下,先定一个小目标:做一个DNF的辅助工具!(也许最终都无法完成也说不定) 这是第一天学习的内容 易语言的优点: 1.     代码是中文的,降低了学习的门槛 2.     全可视化编程,即输即画减少了代码出错的可能 3

  • PHP书写格式详解(必看)

    从一个例子开始. 启动编辑器,创建一个php文件并键入如下代码: <?php echo "你好!"; ?> 将该文件命名为 test.php 并存储于 E:html 目录下. 在浏览器地址栏里访问该 php 文件:http://127.0.0.1/test.php,输出结果如下: 你好!在该例子中,我们以 echo 指令输出一个字符串"你好!". 从这个例子可以看出: •PHP 文件或 PHP 代码段以"<?php"开头,以&q

  • json文件书写格式详解

    目录  JSON是什么 为什么有这个技术 JSON 如何使用 - 数据格式 - 注意事项 - JS 内置两个Json方法 实例:  JSON是什么 JSON ( JavaScript Object Notation) ,是一种数据交互格式. 为什么有这个技术 Json之前,大家都用 XML 传递数据.XML 是一种纯文本格式,所以适合在网络上交换数据,但是 XML 格式比较复杂,终于道格拉斯·克罗克福特(Douglas Crockford)发明了JSON 这种超轻量级的数据交换格式. JSON

  • 解析C++编程中的#include和条件编译

    文件包含的作用 所谓"文件包含"处理是指一个源文件可以将另外一个源文件的全部内容包含进来,即将另外的文件包含到本文件之中.C++提供了#include命令用来实现"文件包含"的操作.如在file1.cpp中有以下#include命令: #include ″file2.cpp″ 它的作用见图示意. "文件包含"命令是很有用的,它可以节省程序设计人员的重复劳动. #include命令的应用很广泛,绝大多数C++程序中都包括#include命令.现在,

  • 深入解析Java编程中方法的参数传递

    在阅读本文之前,根据自己的经验和理解,大家可以先思考并选择一下Java函数的参数传递方式: A. 是按值传递的? B. 按引用传递的? C. 部分按值部分按引用? 此处暂不宣布正确答案,我们通过一个简单的例子让大家自己找答案: 1. 先定义一个类型Value public static class Value { private String value = "value"; public String getValue() { return value; } public void

  • 深入解析golang编程中函数的用法

    函数是一组一起执行任务的语句.每Go程序具有至少一个函数,它一般是main(),以及所有的最琐碎程序可以定义附加函数. 你可以将代码放到独立的功能.如何划分代码之间的不同功能,但逻辑上的划分通常是让每个函数执行特定的任务. 函数声明告诉编译器有关的函数的名称,返回类型和参数.一个函数定义提供了函数的实际主体. Go语言标准库提供了大量的内置函数,在程序可以调用.例如,函数len()需要不同类型的参数和返回值的类型的长度.例如,如果一个字符串传递给它,它会返回字符串的长度以字节为单位,如果一个数组

随机推荐