首页 文章

C#的隐藏功能? [关闭]

提问于
浏览
1476

在我从this question了解到以下内容后,我想到了这一点:

where T : struct

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

我们中的一些人甚至掌握了Genericsanonymous typeslambdasLINQ等东西......

但是,即使C#粉丝,瘾君子,专家几乎不知道C#最隐藏的功能或技巧是什么?

到目前为止,这是显示的功能:

关键词

属性

语法

18944 ??(coalesce nulls)运算符kokos

语言功能

Visual Studio功能

框架

方法和属性

提示与技巧

  • 事件处理程序的好方法Andreas H.R. Nilsson

  • John的大写比较

  • 通过dp访问没有反射的匿名类型

  • 通过Will懒惰地实例化集合属性的快捷方法

  • 类似JavaScript的匿名内联函数roosteronacid

其他

30 回答

  • 103

    这个不是“隐藏”的,因为它被误解了 .

    很多注意力都集中在算法“map”,“reduce”和“filter”上 . 大多数人没有意识到的是.NET 3.5添加了所有这三种算法,但基于它们是LINQ的一部分,它给了它们非常的SQL-ish名称 .

    “map”=>选择将数据从一种形式转换为另一种形式“reduce”=>将聚合聚合值转换为单个结果“filter”=>其中根据条件筛选数据

    使用LINQ对过去采用迭代和条件的集合进行内联工作的能力非常有 Value . 值得了解所有LINQ扩展方法如何帮助您的代码更加紧凑和可维护 .

  • 305

    对于真正使用 System.IO.Path.Combine() 的人来说,这并不是他们应该做到的 . 实际上,整个Path类非常有用,但 no one uses it!

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

    string path = dir + "\\" + fileName;
    
  • 146
    Environment.NewLine
    

    用于系统独立的换行符 .

  • 193

    我倾向于发现大多数C#开发人员都不知道'可空'类型 . 基本上,可以具有空值的基元 .

    double? num1 = null; 
    double num2 = num1 ?? -100;
    

    将可空双精度数num1设置为null,然后将常规双精度数num2设置为num1或-100(如果num1为空) .

    http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

    关于Nullable类型还有一件事:

    DateTime? tmp = new DateTime();
    tmp = null;
    return tmp.ToString();
    

    它返回String.Empty . 有关详细信息,请查看this链接

  • 131

    混入 . 基本上,如果要向多个类添加一个功能,但不能为所有类使用一个基类,请让每个类实现一个接口(没有成员) . 然后,写一个扩展方法 for the interface ,即

    public static DeepCopy(this IPrototype p) { ... }
    

    当然,牺牲一些清晰度 . 但它的确有效!

  • 438

    如果要在不调用任何finally块或终结器的情况下退出程序,请使用FailFast

    Environment.FailFast()
    
  • 185

    使用@作为关键字的变量名 .

    var @object = new object();
    var @string = "";
    var @if = IpsoFacto();
    
  • 117

    我最喜欢的技巧是使用null coalesce operator和括号为我自动实例化集合 .

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

    Unions (the C++ shared memory kind) in pure, safe C#

    如果不采用不安全的模式和指针,您可以让类成员在类/结构中共享内存空间 . 鉴于以下课程:

    [StructLayout(LayoutKind.Explicit)]
    public class A
    {
        [FieldOffset(0)]
        public byte One;
    
        [FieldOffset(1)]
        public byte Two;
    
        [FieldOffset(2)]
        public byte Three;
    
        [FieldOffset(3)]
        public byte Four;
    
        [FieldOffset(0)]
        public int Int32;
    }
    

    您可以通过操作Int32字段来修改字节字段的值,反之亦然 . 例如,这个程序:

    static void Main(string[] args)
        {
            A a = new A { Int32 = int.MaxValue };
    
            Console.WriteLine(a.Int32);
            Console.WriteLine("{0:X} {1:X} {2:X} {3:X}", a.One, a.Two, a.Three, a.Four);
    
            a.Four = 0;
            a.Three = 0;
            Console.WriteLine(a.Int32);
        }
    

    输出:

    2147483647
    FF FF FF 7F
    65535
    

    只需使用System.Runtime.InteropServices添加;

  • 176

    从方法返回匿名类型并访问成员而不进行反射 .

    // Useful? probably not.
    private void foo()
    {
        var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
        Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
    }
    
    object GetUserTuple()
    {
        return new { Name = "dp", Badges = 5 };
    }    
    
    // Using the magic of Type Inference...
    static T AnonCast<T>(object obj, T t)
    {
       return (T) obj;
    }
    
  • 111

    Avoid checking for null event handlers

    在声明时向事件添加一个空委托,禁止在调用它之前总是检查该事件是否真棒 . 例:

    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关于此主题的related discussionblog post(以及可能存在的缺点) .

  • 528

    来自Rick Strahl

    你可以链?运算符,以便您可以进行一堆空比较 .

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

    该泛型类型中的'default'关键字:

    T t = default(T);
    

    如果T是引用类型,则返回'null';如果是int,则返回0;如果是布尔值,则返回false,等等 .

  • 168

    以下是一些有趣的隐藏C#功能,以未记录的C#关键字的形式:

    __makeref
    
    __reftype
    
    __refvalue
    
    __arglist
    

    这些是未记录的C#关键字(甚至Visual Studio识别它们!),这些关键字是为了在泛型之前更有效的装箱/拆箱而添加的 . 它们与System.TypedReference结构协同工作 .

    还有__arglist,用于可变长度参数列表 .

    人们不太了解的一件事是System.WeakReference - 一个非常有用的类,它跟踪一个对象,但仍然允许垃圾收集器收集它 .

    最有用的"hidden"功能是yield return关键字 . 它知道了吗 . LINQ Build 于此之上;它允许通过在引擎盖下生成状态机来执行延迟执行的查询 . Raymond Chen最近发布了关于internal, gritty details的文章 .

  • 142

    这是正则表达式和文件路径的一个有用的:

    "c:\\program files\\oldway"
    @"c:\program file\newway"
    

    @告诉编译器忽略字符串中的任何转义字符 .

  • 585

    我认为C#(.NET 3.5)中最不受欢迎和鲜为人知的功能之一是Expression Treesespecially 与Generics和Lambdas结合使用时 . 这是一种API创建方法,像NInject和Moq这样的新库正在使用 .

    例如,假设我想要使用API注册方法,并且API需要获取方法名称

    鉴于此课程:

    public class MyClass
    {
         public void SomeMethod() { /* Do Something */ }
    }
    

    之前,通常看到开发人员使用字符串和类型(或其他主要基于字符串的方式)执行此操作:

    RegisterMethod(typeof(MyClass), "SomeMethod");
    

    嗯,由于缺乏强力打字,这很糟糕 . 如果我重命名“SomeMethod”怎么办?现在,在3.5中,我可以以强类型的方式执行此操作:

    RegisterMethod<MyClass>(cl => cl.SomeMethod());
    

    其中RegisterMethod类使用 Expression<Action<T>> ,如下所示:

    void RegisterMethod<T>(Expression<Action<T>> action) where T : class
    {
        var expression = (action.Body as MethodCallExpression);
    
        if (expression != null)
        {
            // TODO: Register method
            Console.WriteLine(expression.Method.Name);
        }
    }
    

    这是我现在爱上Lambdas和Expression Trees的一个重要原因 .

  • 115
    • ?? - 合并运算符

    • using(statement / directive) - 非常好的关键字,不仅可以用于调用Dispose

    • readonly - 应该多用

    • netmodules - 太糟糕了,Visual Studio中没有支持

  • 220

    从CLR到C#:规范化字符串时,强烈建议您使用ToUpperInvariant而不是ToLowerInvariant,因为Microsoft已优化了执行大写比较的代码 .

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

  • 409

    属性一般,但最重要的是DebuggerDisplay . 为您节省数年 .

  • 455

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

    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()}
    
  • 209

    @Ed,我对发布这个有点保持沉默,因为它只不过是挑剔 . 但是,我会在您的代码示例中指出:

    MyClass c;
      if (obj is MyClass)
        c = obj as MyClass
    

    如果您打算使用'is',为什么要使用'as'进行安全投射?如果你确定obj确实是MyClass,那么沼泽标准的演员:

    c = (MyClass)obj
    

    ......永远不会失败 .

    同样,你可以说:

    MyClass c = obj as MyClass;
    if(c != null)
    {
       ...
    }
    

    我不太了解.NET的内部结构,但我的直觉告诉我,这会将最多两次类型转换操作减少到最多一次 . 无论如何,它几乎不可能破坏处理银行;就个人而言,我认为后一种形式看起来也更清洁 .

  • 104

    如果您尝试在String.Format表达式中使用大括号...

    int foo = 3;
    string bar = "blind mice";
    String.Format("{{I am in brackets!}} {0} {1}", foo, bar);
    //Outputs "{I am in brackets!} 3 blind mice"
    
  • 286

    lambdas and type inferrence 被低估了 . Lambdas can have multiple statements 和他们 double as a compatible delegate object 自动(只是确保签名匹配),如:

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

    请注意,我没有 new CancellationEventHandler ,也不必指定 sendere 的类型,它们可以从事件中输入 . 这就是为什么编写整个 delegate (blah blah) 并不需要您指定参数类型的麻烦 .

    Lambdas don't need to return anything 和类型推断在这样的上下文中非常强大 .

    顺便说一句,你总是可以在函数式编程意义上返回 Lambdas that make Lambdas . 例如,这是一个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中的指针,我认为这是你应该学习的另一个基本的东西:-)

  • 226

    别名仿制药:

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

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

    当你在很多地方使用相同的通用大而复杂的东西时使用它 .

  • 198

    @告诉编译器忽略字符串中的任何转义字符 .

    只是想澄清一下......它并没有告诉它忽略转义字符,它实际上告诉编译器将字符串解释为文字 .

    如果你有

    string s = @"cat
                 dog
                 fish"
    

    它实际上会打印出来(注意它甚至包括用于缩进的空格):

    cat
                 dog
                 fish
    
  • 314

    其他一切,加上

    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();
    
  • 752

    我会想到“yield” . 像[DefaultValue()]这样的一些属性也是我的最爱 .

    var”关键字更为人所知,但您也可以在.NET 2.0应用程序中使用它(只要您将其设置为输出2.0代码),这似乎并不是很清楚 .

    编辑:kokos,谢谢指出??运营商,'s indeed really useful. Since it'有点难以谷歌(因为??只是被忽略),这是该运营商的MSDN文档页面:?? Operator (C# Reference)

  • 221

    不知道为什么有人会想要使用Nullable <bool> . :-)

    真,假,FileNotFound

  • 262

    也许不是一种先进的技术,但我总是看到让我疯狂的一种技术:

    if (x == 1)
    {
       x = 2;
    }
    else
    {
       x = 3;
    }
    

    可以浓缩为:

    x = (x==1) ? 2 : 3;
    
  • 255

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

    MyClass myObject = (MyClass) obj;
    

    VS

    MyClass myObject = obj as MyClass;
    

    如果obj不是MyClass,则第二个将返回null,而不是抛出类强制转换异常 .

相关问题