波兰与白俄罗斯的边境将于北京时间9月25日6时起重新开放。时隔13天,抵达波兰境内枢纽的中欧班列即将恢复运行。 据央视新闻报道,9月24日,白俄罗斯国...
2025-09-25 8
C# 二十年语法变迁之 C# 2,C# 3 ,C# 4参考
/
自从 C# 于 2000 年推出以来,该语言的规模已经大大增加,我不确定任何人是否有可能在任何时候都对每一种语言特性都有深入的了解。因此,我想写一系列快速参考文章,总结自 C# 2.0 以来所有主要的新语言特性。我不会详细介绍它们中的任何一个,但我希望这个系列可以作为我自己(希望你也是!)的参考,我可以不时回过头来记住我使用的工具工具箱里有。:)
开始之前的一个小提示:我将跳过一些更基本的东西(例如 C# 2.0 引入了泛型,但它们的使用范围如此广泛,以至于它们不值得包括在内);而且我还可以将一些功能“粘合”在一起,以使其更简洁。本系列并不打算成为该语言的权威或历史记录。相反,它更像是可能派上用场的重要语言功能的“备忘单”。
C# 2.0 可空值类型
这些允许您将null指定为任何结构变量的潜在值(否则null将无效):
publicMyClass(int?input){// input can be nullMyInt=input !=null?input.Value:0;// .Value throws an exception when accessed if input is nullMyNullableInt=input;}}
staticvoidTest{varmc =newMyClass(null);if(mc.MyNullableInt==null)Console.WriteLine("Was null!");}
• “可空值类型” 从技术上讲,任何可空值对象的类型都是Nullable ,其中T是实际包含的类型(即int?与Nullable 相同)。Nullable 本身就是一个结构,因此理论上检查该类型的实例是否为null是没有意义的,但是编译器和Nullable 上重写的Equals实现的组合允许我们将实例视为类型好像它确实有意义。您还可以通过使用其HasValue属性来确定Nullable 实例是否为“非空” 。
部分类型partial class
此功能允许将大型类型(类、接口或结构)的实现分散到多个文件中。
publicpartialclassExampleClass{publicvoidDoAlphaOne{...}
publicvoidDoAlphaTwo{...}}
// File: ExampleClass.Beta.cs
publicpartialclassExampleClass{publicvoidDoBetaOne{...}
展开全文
publicvoidDoBetaTwo{...}}
// Elsewhere
staticvoidTest{varec =newExampleClass;
ec.DoAlphaOne;ec.DoBetaTwo;// etc}
• “部分类”
空值合并
此功能允许创建计算为链中第一个非空值的表达式:
全屏查看代码 [1] • “Null Coalesceing” 此代码会将neverNullString设置为_stringField,除非_stringField为空;在这种情况下,它将把它设置为stringParameter,除非stringParameter也为空,在这种情况下,它将把它设置为文字值"Default"。
迭代器生成器(Yield)
此功能允许您通过在可枚举中“生成”元素来创建IEnumerable 或IEnumerator 。下面的例子演示了我们如何创建一个由三个或六个整数组成的序列:
Console.WriteLine(String.Join(",",GetOneTwoThree));// Prints "1,2,3" on consoleConsole.WriteLine(String.Join(",",GetOneTwoThree(true)));// Prints "1,2,3,-1,-2,-3" on console
全屏查看代码 [2] • “收益回报和中断”
C# 3.0 扩展方法
此功能允许在预先存在的类型上定义新方法。这对于向您无法控制的类型添加功能很有用。以下示例显示 如何将ToString的重载添加到double类型:
// ... Elsewhere ...
// Will write something like "3.5"; assuming YearsWorkedAtCompany is a double:Console.WriteLine(user.YearsWorkedAtCompany.ToString(1));
• “ ToString 扩展”
集合初始化器
此功能允许实例化各种集合类型,同时向它们添加初始值:
• “集合初始化器”
对象初始化器
此功能允许在其实例化点设置对象的内联属性:
staticvoidTest{varperson =newPerson{Name="Ben",Age=30};}
• “对象初始化器”
Partial Methods
与部分类一样,这允许您在不同的文件中编写方法的两个或多个部分。不保证执行顺序。该方法必须具有void返回类型,并且必须是私有的。
publicpartialclassExampleClass{publicvoidPrint=>DoThing;
partialvoidDoThing{Console.WriteLine("AAA");}}
// File: ExampleClass.Beta.cs
publicpartialclassExampleClass{partialvoidDoThing{Console.WriteLine("BBB");}}
// Elsewhere
staticvoidTest{varec =newExampleClass;
ec.Print;// Prints AAA and BBB to console (order unspecified).}
• “部分方法” 自动生成的代码可以使用空的部分方法声明,以允许用户在需要时手动插入自定义逻辑:
publicpartialclassExampleClass{publicvoidSomeAutoGeneratedMethod{DoSomethingOnAutoGenMethodCall;
// do other stuff}
partialvoidDoSomethingOnAutoGenMethodCall;// If user does not supply implementation in ExampleClass.User.cs this method will not even be compiled and calls to it will be removed}
// File: ExampleClass.User.cs
publicpartialclassExampleClass{partialvoidDoSomethingOnAutoGenMethodCall{Console.WriteLine("SomeAutoGeneratedMethod Invoked");}}
• “自动生成代码的部分方法”
C# 4.0 动态/后期绑定类型
引入了动态类型以允许“后期绑定”类型解析。我偶尔使用动态的一件事是作为一种更简洁的反射形式:
classProgram{staticvoidMain{vargc =newGenericClass<int,string>;varresultA =InvokeComplexMethodReflectively(gc,"Hi",3f);varresultB =InvokeComplexMethodDynamically(gc,"Hi",3f);
Console.WriteLine(resultA);Console.WriteLine(resultB);}
staticobjectInvokeComplexMethodReflectively(objectgenericClassInstance,stringinputA,floatinputB){varopenMethodDefinition =genericClassInstance.GetType.GetMethod("SomeComplexMethod");vargenericMethodDefinition =openMethodDefinition.MakeGenericMethod(typeof(float));returngenericMethodDefinition.Invoke(genericClassInstance,newobject[]{inputA,inputB });}
staticobjectInvokeComplexMethodDynamically(objectgenericClassInstance,stringinputA,floatinputB){return((dynamic)genericClassInstance).SomeComplexMethod(inputA,inputB);}}
• “动态替代反射” 很多人根本就对使用动态有所保留,但是后期绑定无论如何都是在内部使用反射解决的,所以它真的可以被认为是反射的语法糖。此外,由于绑定信息的缓存,动态实际上通常可以胜过使用“纯”反射的相同方法。
C# 还添加了一个名为ExpandoObject的新类型,它类似于字典,但键是动态添加的成员:
// Prints "User Name is Ben" and "User Age is 30"foreach(varkvp in(IDictionary<String,Object>)user){Console.WriteLine($"User {kvp.Key} is {kvp.Value}");}}
• “ExpandoObject”
可选参数
可选参数是具有指定默认值的方法的参数,因此不需要由调用者指定:
staticvoidTest{MethodWithOptionalArgs("Ben",30);// No nickname specified, 'null' will be passed in}
• “可选参数” 可选参数必须始终排在参数列表的最后。
命名参数
C# 4.0 中的命名参数允许在有多个参数时指定特定的可选参数:
staticvoidTest{MethodWithOptionalArgs("Ben",30,address:"Noveria");// 'nickname' and 'married' are left unspecified}
• “可选参数” 从 C# 7.2 开始,即使参数不是可选的,也可以命名。我偶尔在指定一个布尔参数时使用它,否则它很难理解:
CreateTables(deletePreviousData:true);// Ahh... Much better.}
• “可选参数”
泛型类型参数的协方差和逆变
在使用泛型类型参数创建接口或委托类型时,我们可以指定这些类型参数是协变的或逆变的:
staticvoidTest{ICovariant<object>covariantObj;ICovariant<int>covariantInt =GetCovariant<int>;
covariantObj =covariantInt;// "out T" in ICovariant allows this
IContravariant<object>contravariantObj =GetContravariant<object>;IContravariant<int>contravariantInt;
contravariantInt =contravariantObj;// "in T" in IContravariant allows this}
• “接口中的协变和逆变通用参数”
staticvoidTest{Covariant<object>covariantObj;Covariant<int>covariantInt ==>3;
covariantObj =covariantInt;
Contravariant<object>contravariantObj =myObj =>Console.WriteLine(myObj);Contravariant<int>contravariantInt;
contravariantInt =contravariantObj;}
• “委托中的协变和逆变通用参数”
当指定通常作为接口输出 的对象类型时,协方差很有用;因为我们通常不介意实际的输出类型是否是指定类型的子类型。在指定通常作为接口输入
的对象类型时,逆变很有用。因为我们通常不介意预期的输入类型是否是给定类型的父类型。 与其记住“contra”和“co”方差之间的区别,我发现记住in用于输入而out用于输出(通常,无论如何)是有用的。
References
[1] 全屏查看代码:
[2] 全屏查看代码:
相关文章
波兰与白俄罗斯的边境将于北京时间9月25日6时起重新开放。时隔13天,抵达波兰境内枢纽的中欧班列即将恢复运行。 据央视新闻报道,9月24日,白俄罗斯国...
2025-09-25 8
“我是不是被骗了?” 男子邮寄黄金“投资”后 匆忙跑进派出所向民警求证 民警:这就是诈骗! “警察同志,两天前 我把100克黄金寄到广东投资 会不会有...
2025-09-25 10
当地时间2025年9月21日,俄罗斯,乌克兰航空频道也关注了,在长春航展上中国解放军歼-6无人机。对于中国解放军歼-6无人机展示出来的,令人恐惧的火力...
2025-09-25 7
伊朗,在经历了惨痛的伊以战争后,终于意识到防空能力的重要性。近期有消息称,伊朗正在与中国和俄罗斯进行全方位合作,试图通过引进先进武器来弥补自身防空力量...
2025-09-25 6
北京时间9月25日凌晨2点45分,2025-2026赛季英格兰联赛杯第3轮展开一场焦点战役,曼城前往客场对阵哈德斯菲尔德。上半场,小将穆卡萨做球,福登...
2025-09-25 8
9月23日,西贝公众号发布文章《7岁的毛毛:我以为我再也吃不到西贝了》。 文章以7岁儿童毛毛的视角,讲述了毛毛从2岁起开始吃西贝,妈妈因为最近的新闻不...
2025-09-25 7
这两天在美国纽约举行的联合国大会备受国际社会的关注,作为东道主的特朗普,自然不会放弃这样一个可以“好好表现”的机会,于是我们就看到他在联大会议上,把到...
2025-09-25 8
“我上的不是西北工业大学吗?怎么图书馆上印的是西安工业大学的图书馆?”近日,有西北工业大学的本科新生发现,自己刚发的学生证封面上印的是西安工业大学的图...
2025-09-25 8
发表评论