在我从这个问题中了解到以下内容后,我想到了这一点:

where T : struct

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

我们中的一些人甚至掌握了Generics、匿名类型、lambdas、LINQ等等。。。

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

以下是迄今为止揭示的功能:

关键词

迈克尔·斯图姆的产量Michael Stum的varkokos的using()语句kokos只读由Mike Stone作者:Ed Swangren由Rocketpants改进因死亡而违约全球::由pzycomanAlexCuse的using()块Jakubšturc的挥发性Jakubšturc的外部别名

属性

Michael Stum的DefaultValueAttributeDannySmurf的ObsoleteAttribute调试器DisplayAttribute(按Stu)bdukes提供的DebuggerBrowseble和DebuggerStepThroughmarxidad的ThreadStaticAttributeMartin Clarke的FlagsAttributeAndrewBurns的ConditionalAttribute

语法

?? kokos的(合并空值)运算符Nick Berardi的数字标记其中T:Lars Mæhlum的新Keith的隐式泛型Keith的单参数lambdas基思汽车财产Keith的命名空间别名Patrick的带@的逐字字符串文字按lfoost列出的枚举值@marxidad的variableamesmarxidad的事件运算符由Portman设置字符串括号格式xanadot的属性访问器可访问性修饰符JasonS的条件(三元)运算符(?:)Binoj Antony检查和未检查操作员Flory的隐式和显式运算符

语言功能

Brad Barker的可空类型Keith的匿名类型__由Judah Himango制作的makeref __reftype __refvaluelomaxx的对象初始化器达科他州David的字符串格式marxidad的扩展方法Jon Erickson的部分方法John Asbeck的预处理器指令Robert Durgin的DEBUG预处理器指令SefBkn导致操作员过载通过chakrit推断类型Rob Gough将布尔运算符提升到下一级通过Roman Boiko将值类型变量作为不带装箱的接口传递由Roman Boiko编程确定声明的变量类型Chris的静态构造器使用LINQ by roosteronacid更容易进行眼睛/精简ORM映射__Zac Bowling的arglist

Visual Studio功能

Himadri在编辑器中选择文本块DannySmurf的片段

框架

KiwiCastard的TransactionScopeKiwiAstard的从属事务IainMH的<T>可为空迪亚戈的Mutex按ageektrapped列出的System.IO.PathJuan Manuel的WeakReference

方法和财产

KiwiAstard的String.IsNullOrEmpty()方法KiwiCastard的List.ForEach()方法Will Dean的BeginInvoke()、EndInvoke(()方法Nullable<T>。HasValue和Nullable<T>。Rismo的Value财产John Sheehan的GetValueOrDefault方法

提示和技巧

Andreas H.R.Nilsson的事件处理程序的好方法John的大写比较访问匿名类型而不通过dp进行反射Will延迟实例化集合财产的快速方法chosteronacid提供的类似JavaScript的匿名内联函数

另外

kokos的netmodulesDuncan Smart的LINQBridgeJoel Coehorn的并行扩展


当前回答

在刚刚了解了不变性、协方差和反方差的含义之后,我发现了.NET4.0中包含的内外通用修饰符。它们看起来很晦涩,大多数程序员都不知道。

Visual Studio Magazine上有一篇文章讨论了这些关键字以及如何使用它们。

其他回答

任意嵌套作用域{}


1.对于更精细的范围界定行为

{成员内部的任何位置},{仅使用大括号},}不使用控制语句}。

void MyWritingMethod() {

    int sameAge = 35;


    { // scope some work
        string name = "Joe";
        Log.Write(name + sameAge.ToString());
    }


    { // scope some other work
        string name = "Susan";
        Log.Write(name + sameAge.ToString());
    }

    // I'll never mix up Joe and Susan again
}

在大型、混乱或过时的成员(但它们不应该存在)中,它帮助我防止使用错误的变量名。将内容范围扩大到更精细的级别。

2.用于代码美化或视觉语义

例如,此XML编写代码遵循实际生成的XML的缩进级别(即Visual Studio将相应地缩进范围大括号)

XmlWriter xw = new XmlWriter(..);

//<root>
xw.WriteStartElement("root");
{
    //<game>
    xw.WriteStartElement("game");
    {
        //<score>#</score>
        for (int i = 0; i < scores.Length; ++i) // multiple scores
            xw.WriteElementString("score", scores[i].ToString());

    }
    //</game>
    xw.WriteEndElement();
}
//</root>
xw.WriteEndElement();

3.模仿“with”语句

(另一种用途是将临时工作排除在主要范围之外)Patrik提供:有时用于模仿C#中的VB“with语句”。

var somePerson = this.GetPerson();  // whatever 
{ 
    var p = somePerson; 
    p.FirstName = "John"; 
    p.LastName = "Doe"; 
    //... 
    p.City = "Gotham"; 
} 

对于有眼光的程序员。

嵌套类可以访问外部类的私有成员。

public class Outer
{
    private int Value { get; set; }

    public class Inner
    {
        protected void ModifyOuterMember(Outer outer, int value)
        {
            outer.Value = value;
        }
    }
}

现在,结合上述功能,您还可以继承嵌套类,就像它们是顶级类一样,如下所示。

public class Cheater : Outer.Inner
{
    protected void MakeValue5(Outer outer)
    {
        ModifyOuterMember(outer, 5);
    }
}

这些特性允许一些有趣的可能性,比如通过一些隐藏的类访问特定成员。

可以为枚举定义数据类型:

enum EnumName : [byte, char, int16, int32, int64, uint16, uint32, uint64]
{
    A = 1,
    B = 2
}

我最喜欢的属性:InternalsVisibleTo

在程序集级别,您可以声明另一个程序集可以看到您的内部构件。出于测试目的,这绝对是美妙的。

将其粘贴到AssemblyInfo.cs或等效程序中,测试程序集就可以完全访问所有需要测试的内部内容。

[assembly: InternalsVisibleTo("MyLibrary.Test, PublicKey=0024...5c042cb")]

如您所见,测试程序集必须具有强名称才能获得被测试程序集的信任。

在.Net Framework 2.0+、Compact Framework 2.0+和XNA Framework 1.0+中提供。

我想说,将某些系统类用于扩展方法非常方便,例如system.Enum,您可以执行以下操作。。。

[Flags]
public enum ErrorTypes : int {
    None = 0,
    MissingPassword = 1,
    MissingUsername = 2,
    PasswordIncorrect = 4
}

public static class EnumExtensions {

    public static T Append<T> (this System.Enum type, T value) where T : struct
    {
        return (T)(ValueType)(((int)(ValueType) type | (int)(ValueType) value));
    }

    public static T Remove<T> (this System.Enum type, T value) where T : struct
    {
        return (T)(ValueType)(((int)(ValueType)type & ~(int)(ValueType)value));
    }

    public static bool Has<T> (this System.Enum type, T value) where T : struct
    {
        return (((int)(ValueType)type & (int)(ValueType)value) == (int)(ValueType)value);
    }

}

...

//used like the following...

ErrorTypes error = ErrorTypes.None;
error = error.Append(ErrorTypes.MissingUsername);
error = error.Append(ErrorTypes.MissingPassword);
error = error.Remove(ErrorTypes.MissingUsername);

//then you can check using other methods
if (error.Has(ErrorTypes.MissingUsername)) {
    ...
}

当然,这只是一个例子——这些方法可能需要更多的工作。。。