命名空间主要用于按功能领域组织类型,以便查找和理解这些类型。此外,命名空间还有助于防范类型名称冲突。
C#不支持全局方法,一切都必须在类型声明中。这正是Main方法标记为static的原因。
如果方法又返回类型,它的主体必须没有“不可到达的结束点”。换言之,方法不能在不返回值的情况下碰到大括号而自然结束。
从C#7.0开始多个值可以通过元组语法打包成元组返回。
为简化方法的定义,C#6.0引入了表达式主体方法,允许用表达式代替完整方法主体。
和C++不同C#类从来不将实现与声明分开(C#确实支持名为“分部方法”的高级功能,允许将方法的声明和实现分开)。
static string GetFullName( string firstName, string lastName) =>
$"{ firstName } { lastName }";
using指令不“导入”任何嵌套命名空间中的类型,虽然添加了using System;,但要访问System.Text中的StringBuilder类型必须添加一个using System.Text指令或对类型进行完全限定。
在java中可以用通配符导入命名空间,但C#不允许,每个命名空间都必须显示导入。
可以利用using指令为命名空间或类型取一个别名。别名的两个最常见的用途是消除两个同名类型的歧义和缩写长名称。
C#支持在执行程序时提供命令行参数,并允许从Main()方法返回状态标识符。
参数默认采用传值方式。
int a=123;
string b="456";
ClassC c=new ClassC();
func(a,b,c);
func(int a,string b,ClassC c)
{
...
}
上面的调用中,a传的是123这个数值,b传的是"456"这个字符串字面值,c传的是c指向的对象的引用(地址),也就是c这个变量的值。
这些值传进函数里后赋值给了函数里的a,b,c,所以函数里的abc是新创建的局部变量。给c的某个成员赋值会影响外面的c,因为c都指向同一个对象。但如果给c变量new一个新对象,不会对外面的c造成影响,因为c是局部变量。字符串同理。
调用者应初始化传引用的局部变量。
函数里的ref参数只是传递的变量的别名,换言之,引用参数的作用只是为现有变量分配参数名,而非创建新变量并将实参的值拷贝给它。
out参数功能上与ref参数完全一致,区别就是C#语言对别名变量的读写又不同规定。如参数被标记为out,编译器会核实在方法所有正常返回的代码路径中,是否都对该参数进行了赋值。
从C#7.0起可在调用方法前以内联的形式声明out变量,而不必在使用前声明out变量。
C#7.0的另一个功能是允许完全放弃out参数,可用下划线放弃参数:
TryGetPhoneButton(character,out _);
C#7.0写代码时,返回两个或更多值应首选元组语法。
C#7.2支持以传引用的方式传入只读值类型。避免了每次调用方法都创建值类型的拷贝,而且不用担心值类型参数被修改。换言之,其作用是在传值时减少拷贝量,为参数添加in修饰符。
C#7.0新增的另一个功能返回对变量的引用。
// Returning a reference
public static ref byte FindFirstRedEyePixel(byte[] image)
{
// Do fancy image detection perhaps with machine learning
for (int counter = 0; counter < image.Length; counter++)
{
if (image[counter] == (byte)ConsoleColor.Red)
{
return ref image[counter];
}
}
throw new InvalidOperationException("No pixels are red.");
}
public static void Main()
{
byte[] image = new byte[254];
// Load image
int index = new Random().Next(0, image.Length - 1);
image[index] =
(byte)ConsoleColor.Red;
Console.WriteLine(
$"image[{index}]={(ConsoleColor)image[index]}");
// ...
// Obtain a reference to the first red pixel
ref byte redPixel = ref FindFirstRedEyePixel(image);
// Update it to be Black
redPixel = (byte)ConsoleColor.Black;
Console.WriteLine(
$"image[{index}]={(ConsoleColor)image[redPixel]}");
}
ref局部变量被初始化为引用一个特定变量,以后不能修改为引用其他变量。(有点像C++里引用了)
要么以逗号分隔的字符串参数,要么是单个字符串数组,声明了参数数组之后,每个参数都作为参数数组的成员来访问。
参数数组必须是最后一个,所以只能有一个。
方法重载是一种**操作性多态(**operational polymorphism)。如由于数据变化造成同一个逻辑操作具有许多形态,就会发生多态。
C#4.0新增了对可选参数的支持。可选参数一点要放到所有必须参数后面。默认值必须是常量或者其他能在编译时确定的值。
C#4.0新增的另一个方法调用功能是具名参数,
public static void Main()
{
DisplayGreeting(
firstName: "Inigo", lastName: "Montoya");
}
public static void DisplayGreeting(
string firstName,
string? middleName = null,
string? lastName = null
)
{
// ...
}
如果一个方法有大量参数,许多都可选,那么具名参数语法肯定能带来不少遍历,但代价是牺牲了方法接口的灵活性,参数名变成了方法接口的一部分。
假如由于其中一个方法有可选参数使得两个方法都适用,编译器最终将选择无可选参数的方法。