我想了解C#的所有便利功能,以及它们如何映射到C#。
例如,自动属性:
public string Foo { get; set; }
...映射到这样的东西:
string <Foo>k__BackingField;
[CompilerGenerated]
public string Foo {
get { return this.<Foo>k__BackingField; }
set { this.<Foo>k__BackingField = value; }
}
Foreach循环:
foreach(char c in "Hello") {
Console.WriteLine(c);
}
...映射到这样的东西(我想):
CharEnumerator en;
try {
en = "Hello".GetEnumerator();
while (en.MoveNext()) {
char c = en.Current;
Console.WriteLine(c);
}
} finally {
IDisposable disp = en as IDisposable;
if (disp != null)
disp.Dispose();
}
在处理非托管资源时,处理枚举器使foreach
非常有用,例如循环文件中的行或数据库中的记录。
我认为对这些高级功能的良好理解可以帮助我们编写更好的代码。 C#的其他便利功能有哪些?它们如何映射到C#?
答案 0 :(得分:11)
如果您想谈谈保存的代码量,最大的储户(IMO)是:
迭代器块
示例:
public static IEnumerable<int> Get() {yield return 1; yield return 2;}
保存:
IEnumerable<T>
实施IEnumerator<T>
实施捕获变量(anon methods / lambdas)
示例:
var list2 = list1.FindAll(x => (x.Value % 10) == find);
保存:
表达式lambda编译器
示例(来自上方):
Expression<Func<Foo,bool>> pred = x => (x.Value % 10) == find;
保存:
Expression.Parameter
,Expression.Property
,Expression.Field
,Expression.Constant
,Expression.Equal
,Expression.Modulo
,{{ 1}} ...结合; -p 答案 1 :(得分:8)
使用是语法糖
using(x)
{
...
}
映射到
try {
// Code
}
finally
{
if(x != null)
((IDisposable)x).Dispose();
}
LINQ中的东西是语法糖
from x in l where y select z;
转换为
l.Where(x => y).Select(x => z);
答案 2 :(得分:6)
LINQ作为一个整体(特别是使用LINQ查询语法)本质上是一个主要的C#/ .NET便利功能,它在很多时候取代了for循环/迭代器/复杂查询逻辑。
答案 3 :(得分:5)
for
,while
,do
... while
,switch
- 一个有争议的答案:)
您可以使用基于if
和goto
的部分代码替换它。
lock(){}
可以在try-finally中使用null检查转换为Monitor.Enter()和Monitor.Exit()(参见Does a locked object stay locked if an exception occurs inside it?)
答案 4 :(得分:4)
The ?: operator,它测试一个布尔或布尔表达式,如果测试返回true
则返回第一个值,如果测试返回false
则返回第二个值:
condition ? first_expression : second_expression
本质上意味着:
var x;
if (condition)
{
x = first_expression;
}
else
{
x = second_expression
}
使用?:运算符,您可以编写int x = condition ? 10 : 20;
,而不必写出整个if
语句。
答案 5 :(得分:3)
对象初始值设定项非常合理:
public class Book
{
public string Author { get; set; }
public string Title { get; set; }
}
Book book = new Book() {Author = "John Smith", Title = "C# Syntax"};
以上是另一种写作方式:
Book book = new Book();
book.Author = "John Smith";
book.Title = "C# Syntax";
隐含类型:
var book = new Book() {Author = "John Smith", Title = "C# Syntax"};
答案 6 :(得分:3)
null coalescing operator(??)非常漂亮。这......
ISomeRef myRef = firstChoice ?? secondChoice ?? fallback;
转换为等同于:
的功能ISomeRef myRef = firstChoice;
if(myRef == null) myRef = secondChoice;
if(myRef == null) myRef = fallback;
我说功能相当,因为我还没有看过反射器:)
答案 7 :(得分:3)
匿名类型:
var message = new { Message = "Hello, world!", MessageID = 1 };
被翻译为
<>f__AnonymousType0<string, int> message =
new <>f__AnonymousType0<string, int>("Hello, world!", 1);
,其中
[CompilerGenerated]
[DebuggerDisplay(
@"\{ Message = {Message},
MessageID = {MessageID} }",
Type="<Anonymous Type>"
)
]
internal sealed class <>f__AnonymousType0<
<Message>j__TPar,
<MessageID>j__TPar
> {
// Fields
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly <Message>j__TPar <Message>i__Field;
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly <MessageID>j__TPar <MessageID>i__Field;
// Methods
[DebuggerHidden]
public <>f__AnonymousType0(
<Message>j__TPar Message,
<MessageID>j__TPar MessageID
) {
this.<Message>i__Field = Message;
this.<MessageID>i__Field = MessageID;
}
[DebuggerHidden]
public override bool Equals(object value) {
var type = value as <>f__AnonymousType0<
<Message>j__TPar,
<MessageID>j__TPar
>;
return (((type != null) &&
EqualityComparer<<Message>j__TPar>.Default.Equals(
this.<Message>i__Field,
type.<Message>i__Field)
) &&
EqualityComparer<<MessageID>j__TPar>.Default.Equals(
this.<MessageID>i__Field,
type.<MessageID>i__Field)
);
}
[DebuggerHidden]
public override int GetHashCode() {
int num = 0x2e22c70c;
num = (-1521134295 * num) +
EqualityComparer<<Message>j__TPar>.Default.GetHashCode(
this.<Message>i__Field
);
return ((-1521134295 * num) +
EqualityComparer<<MessageID>j__TPar>.Default.GetHashCode(
this.<MessageID>i__Field)
);
}
[DebuggerHidden]
public override string ToString() {
StringBuilder builder = new StringBuilder();
builder.Append("{ Message = ");
builder.Append(this.<Message>i__Field);
builder.Append(", MessageID = ");
builder.Append(this.<MessageID>i__Field);
builder.Append(" }");
return builder.ToString();
}
// Properties
public <Message>j__TPar Message {
get {
return this.<Message>i__Field;
}
}
public <MessageID>j__TPar MessageID {
get {
return this.<MessageID>i__Field;
}
}
}
答案 8 :(得分:3)
匿名委托在编译期间变为方法,所以:
var collection = new[] { 1, 2, 3, 4 }.Where(i => i == 2);
导致创建一个新方法:
[CompilerGenerated]
private static bool <Main>b__0(int i)
{
return (i == 2);
}
并更改为:
IEnumerable<int> collection = new int[] { 1, 2, 3, 4 }.Where<int>(<Main>b__0);
请注意,它使用的是在编译<Main>b__0
之前无法创建的方法名称 - 您不能在方法名称中使用<>
,因此它始终可以避免冲突。
同样的过程以及i => i == 2
:
delegate(int i) { return i == 2; }
您还会注意到您可以使用简写:
new[] { 1, 2, 3, 4 }
// goes to...
new int[] { 1, 2, 3, 4 }
和
var foo = new Foo();
// goes to...
Foo foo = new Foo();
答案 9 :(得分:1)
Lambda表达式是另一个例子。
var myZombies = myMonsters.Where(monster => monster.Kind == MonsterKind.Zombie);
使用一个奇怪的名称将Lambda委托拉出到自己的方法中。
你可以使用Reflector并在选项对话框中的C#版本之间切换,看看这些事情将如何解决的差异。
答案 10 :(得分:1)
Nullable<T>
是另一个令人难以置信的便利。特别方便的是?
语法,因为int?
是Nullable<int>
的缩写。
答案 11 :(得分:1)
扩展方法。
如果这是您的扩展方法:
static class ObjectExtensions
{
public void ExtensionMethod(this object obj)
{
// Do something here...
}
}
您致电obj.ExtensionMethod()
它转换为:
ObjectExtensions.ExtensionMethod(obj)
如果您碰巧有一个支持扩展方法的C#编译器版本,您可以通过创建System.Runtime.CompilerServices.ExtensionAttribute
来欺骗编译器让您在3.5之前的.Net版本中使用扩展方法,如下所示: (这样做非常安全,因为编译器将扩展方法映射到标准IL)
namespace System.Runtime.CompilerServices
{
using System;
internal sealed class ExtensionAttribute : Attribute
{
}
}
答案 12 :(得分:0)
在高级语言中不常见,C#有一个'goto'语句,因此其他几个C#语句可以被认为是goto语句的语言翻译。
例如,if()语句直接映射到goto,而()循环的标准实际映射到映射到goto的while()循环。
switch()语句很不寻常,因为根据case的数量和switch参数的类型进行不同的编译。因此,不可能将其视为转换的语言转换。
答案 13 :(得分:0)
集合初始值设定项(和类型推断):
var scoobies = new List<Scooby>()
{
new Scooby("Buffy"),
new Scooby("Willow"),
new Scooby("Xander")
};
地图:
List<Scooby>() scoobies = new List<Scooby>();
scoobies.Add(new Scooby("Buffy"));
scoobies.Add(new Scooby("Willow"));
scoobies.Add(new Scooby("Xander"));