C#到C#,方便的语言功能

时间:2010-01-09 21:43:31

标签: c# .net

我想了解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#?

14 个答案:

答案 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;

保存:

  • yeuch - 很多树代码;非常非常复杂;在上面我可以看到(没有特别的顺序)Expression.ParameterExpression.PropertyExpression.FieldExpression.ConstantExpression.EqualExpression.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)

  1. forwhiledo ... whileswitch - 一个有争议的答案:)

    您可以使用基于ifgoto的部分代码替换它。

  2. 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"));