C#的隐藏功能?

这个问题中学到以下内容后,我想到了这一点

where T : struct

我们 C#开发人员都知道 C#的基础知识。我的意思是声明,条件,循环,运算符等。

我们中有些人甚至掌握了泛型匿名类型lambdasLINQ等...

但是,即使 C#爱好者,成瘾者,专家也几乎不知道 C#最隐藏的功能或技巧是什么?

到目前为止,这里是一些揭示的功能:


答案

这本身不是 C#,但是我还没有见过真正使用System.IO.Path.Combine()的人。实际上,整个 Path 类确实很有用,但是没有人使用它!

我敢打赌,每个生产应用程序都具有以下代码,即使它不应该具有以下代码:

string path = dir + "\\" + fileName;

lambda 和类型推断被低估了。 Lambda 可以具有多个语句,并且它们可以自动兼用作兼容的委托对象 (只需确保签名匹配),如下所示:

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

请注意,我没有new CancellationEventHandler也不必指定sendere类型,它们可以从事件中推断出来。这就是为什么这样写完整的delegate (blah blah)麻烦,这也需要您指定参数的类型。

Lambda 不需要返回任何内容,并且在这种情况下类型推断非常强大。

顺便说一句,您始终可以返回在函数式编程意义上构成 Lambda 的 Lambda 。例如,以下是一个 lambda,它使 lambda 可以处理 Button.Click 事件:

Func<int, int, EventHandler> makeHandler =
    (dx, dy) => (sender, e) => {
        var btn = (Button) sender;
        btn.Top += dy;
        btn.Left += dx;
    };

btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);

注意链接: (dx, dy) => (sender, e) =>

这就是为什么我很高兴参加函数式编程课程的原因:-)

除了 C 中的指针,我认为这是您还应该学习的另一项基本知识:-)

来自里克 · 斯特拉尔Rick Strahl)

您可以链接?? 运算符,以便您可以进行一系列空比较。

string result = value1 ?? value2 ?? value3 ?? String.Empty;

别名泛型:

using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

它允许您使用ASimpleName ,而不是Dictionary<string, Dictionary<string, List<string>>>

当您在许多地方使用相同的通用大型长复杂事物时,请使用它。

CLR 通过 C#

规范化字符串时,强烈建议您使用 ToUpperInvariant 而不是 ToLowerInvariant,因为Microsoft 已经优化了用于执行大写比较的代码

我记得有一次我的同事总是在比较之前将字符串更改为大写。我一直想知道他为什么这样做,因为我觉得先转换为小写字母更 “自然”。看完这本书后,我知道为什么了。

我最喜欢的技巧是使用null 合并运算符和括号自动为我实例化集合。

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }

避免检查空事件处理程序

在声明时向事件添加一个空的委托,从而消除了在调用该事件之前总是检查该事件是否为 null 的需要。例:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

让你做

public void DoSomething()
{
    Click(this, "foo");
}

代替这个

public void DoSomething()
{
    // Unnecessary!
    MyClickHandler click = Click;
    if (click != null) // Unnecessary! 
    {
        click(this, "foo");
    }
}

另请参阅此相关讨论以及 Eric Lippert 的有关此主题的博客文章 (以及可能存在的弊端)。

其他一切,再加上

1)隐式泛型(为什么只对方法而不对类?)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2)具有一个参数的简单 lambda:

x => x.ToString() //simplify so many calls

3)匿名类型和初始化程序:

//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
    { "red", "#ff0000" },
    { "green", "#00ff00" },
    { "blue", "#0000ff" }
};

int[] arrayOfInt = { 1, 2, 3, 4, 5 };

另一个:

4)自动属性可以具有不同的范围:

public int MyId { get; private set; }

感谢 @pzycoman 提醒我:

5)命名空间别名(并非您可能需要此特殊区别):

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();

我很长一段时间都不知道 “as” 关键字了。

MyClass myObject = (MyClass) obj;

MyClass myObject = obj as MyClass;

如果 obj 不是 MyClass,则第二个将返回 null,而不是引发类强制转换异常。

我喜欢的两件事是自动属性,因此您可以进一步折叠代码:

private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

变成

public string Name { get; set;}

还有对象初始化器:

Employee emp = new Employee();
emp.Name = "John Smith";
emp.StartDate = DateTime.Now();

变成

Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}