C#的隐藏特性?

det 发布于 2019-11-10 c# 最后更新 2019-11-10 11:50 279 浏览

内容太长未翻译

已邀请:

ut_quo

赞同来自:

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

yet

赞同来自:

我无法弄清楚Convert类中的某些函数有什么用(例如Convert.ToDouble(int),Convert.ToInt(double)),直到我将它们与Array.ConvertAll组合:

int[] someArrayYouHaveAsInt;
double[] copyOfArrayAsDouble = Array.ConvertAll<int, double>(
                                someArrayYouHaveAsInt,
                                new Converter<int,double>(Convert.ToDouble));
这避免了定义内联委托/闭包(稍微更具可读性)引起的资源分配问题:
int[] someArrayYouHaveAsInt;
double[] copyOfArrayAsDouble = Array.ConvertAll<int, double>(
                                someArrayYouHaveAsInt,
                                new Converter<int,double>(
                                  delegate(int i) { return (double)i; }
                                ));

ueos

赞同来自:

C#中有一些与TypedReference未记录类相关的隐藏关键字和功能。以下关键字未记录:

  • __makeref
  • __reftype
  • __refvalue
  • __arglist
使用示例:
// Create a typed reference
int i = 1;
TypedReference tr1 = __makeref(i);
// Get the type of a typed reference
Type t = __reftype(tr1);
// Get the value of a typed referece
int j = __refvalue(tr1, int); 
// Create a method that accepts and arbitrary number of typed references
void SomeMethod(__arglist) { ...
// Call the method
int x = 1;
string y = "Foo";
Object o = new Object();
SomeMethod(__arglist(x,y,o));
// And finally iterate over method parameters
void SomeMethod(__arglist) {
    ArgIterator ai = new ArgIterator(__arglist);
while(ai.GetRemainingCount() >0)
{
      TypedReference tr = ai.GetNextArg();
      Console.WriteLine(TypedReference.ToObject(tr));
}}

qui_id

赞同来自:

当与.NET 3.5中的语句lambdas一起使用时,肯定是Func<>类型。这些允许自定义功能,并且可以非常有助于提供用户可自定义的对象而无需对其进行子类化或诉诸某些有限的系统,例如跟踪列出用户想要监视的按钮或键的变量。此外,它们可以像常规方法一样调用,并且可以像变量一样分配。我能想到的唯一缺点就是你只能参加5个论点!虽然到那时你可能想要考虑一个不同的解决方案...... 编辑:提供一些例子。

...
public Func<InputHelper, float> _horizontalCameraMovement = (InputHelper input) => 
{
    return (input.LeftStickPosition.X * _moveRate) * _zoom;
}
public Func<InputHelper, float> _verticalCameraMovement = (InputHelper input) => 
{
    return (-input.LeftStickPosition.Y * _moveRate) * _zoom;
}
...
public void Update(InputHelper input)
{
    ...
    position += new Vector2(_horizontalCameraMovement(input), _verticalCameraMovement(input));
    ...
}
在此示例中,您可以编写一个执行任意计算的函数,并返回一个浮点数,用于确定相机移动的数量。不是最好的代码,但它得到了重点。
private int foo;
public int FooProperty {
    get
    {
        if (_onFooGotten() == true)
            return _foo;
    }
    set
    {
        if (onFooSet() == true)
            _foo = value;
    }
}
...
public Func<bool> _onFooGotten = () => 
{
    //do whatever...
    return true;
}
public Func<bool> _onFooSet = () =>
{
    //do whatever...
    return true;
}
这不是最好的例子(因为我还没有真正探索过这个用法),但它显示了一个使用lambda函数进行快速事件提升的示例,没有代理的麻烦。 编辑:想到另一个。 Nullables! C#与可选参数最接近的东西。

vfugit

赞同来自:

fixed声明 此语句可防止垃圾回收器重定位可移动变量。 Fixed也可用于创建固定大小的缓冲区。

The fixed statement sets a pointer to a managed variable and "pins" that variable during the execution of statement.
stackalloc stackalloc在堆栈上分配一块内存。

lest

赞同来自:

有些运算符用于在声明的类和一个或多个任意类之间执行implicitexplicit用户定义的类型转换。 implicit运算符有效地允许模拟赋值运算符的重载,这在C++等语言中是可能的,而不是C#。 它似乎不是经常遇到的功能,但它实际上在LINQ to XML(System.Xml.Linq)库中使用,您可以在其中隐式地将字符串转换为XName对象。例:

XName tagName = "x:Name";
我在此article中发现了有关如何在C#中模拟多重继承的功能。

tmodi

赞同来自:

PreviousPage属性: “System.Web.UI.Page表示将控件转移到当前页面的页面。” 这非常有用。

qet

赞同来自:

许多人没有意识到他们可以使用OrdinalIgnoreCase来比较字符串,而不必使用someString.ToUpper()。这消除了额外的字符串分配开销。

if( myString.ToUpper() == theirString.ToUpper() ){ ... }
if( myString.Equals( theirString, StringComparison.OrdinalIgnoreCase ) ){ ... }

onon

赞同来自:

这涉及静态构造函数。这是一种执行静态破坏(即在程序退出时清理资源)的方法。 首先下课:

class StaticDestructor
{
    /// <summary>
    /// The delegate that is invoked when the destructor is called.
    /// </summary>
    public delegate void Handler();
    private Handler doDestroy;
/// <summary>
    /// Creates a new static destructor with the specified delegate to handle the destruction.
    /// </summary>
    /// <param name="method">The delegate that will handle destruction.</param>
    public StaticDestructor(Handler method)
    {
        doDestroy = method;
    }
~StaticDestructor()
    {
        doDestroy();
    }
}
然后作为类的成员,你希望有一个“静态析构函数”做:
private static readonly StaticDestructor destructor = new StaticDestructor
(
    delegate()
    {
        //Cleanup here
    }
);
现在将在最终垃圾收集发生时调用此方法。如果您绝对需要释放某些资源,这非常有用。 一个快速而肮脏的程序,表现出这种行为:
using System;
namespace TestStaticDestructor
{
    class StaticDestructor
    {
        public delegate void Handler();
        private Handler doDestroy;
public StaticDestructor(Handler method)
        {
            doDestroy = method;
        }
~StaticDestructor()
        {
            doDestroy();
        }
    }
class SomeClass
    {
        static SomeClass()
        {
            Console.WriteLine("Statically constructed!");
        }
static readonly StaticDestructor destructor = new StaticDestructor(
            delegate()
            {
                Console.WriteLine("Statically destructed!");
            }
        );
    }
class Program
    {
        static void Main(string[] args)
        {
            SomeClass someClass = new SomeClass();
            someClass = null;
            System.Threading.Thread.Sleep(1000);
        }
    }
}
程序退出时,将调用“静态析构函数”。

verror

赞同来自:

我倾向于发现大多数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链接了解更多详情

yut

赞同来自:

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

"map" => Select
Transforms data from one form into another "reduce" => Aggregate
Aggregates values into a single result "filter" => Where
Filters data based on a criteria
使用LINQ对过去采用迭代和条件的集合进行内联工作的能力非常有价值。值得了解所有LINQ扩展方法如何帮助您的代码更加紧凑和可维护。

lqui

赞同来自:

我看不到上面这个 - 我直到最近才意识到你可以做的一个是从另一个调用一个构造函数:

class Example
{
    public Example(int value1)
        : this(value1, "Default Value")
    {
    }
public Example(int value1, string value2)
    {
        m_Value1 = value1;
        m_value2 = value2;
    }
int m_Value1;
    string m_value2;
}

verror

赞同来自:

高级调试

显示 已提到的属性DebuggerDisplay和DebuggerBrowsable控制元素的可见性和显示的文本值。简单地重写ToString()将导致调试器使用该方法的输出。 如果您想要更复杂的输出,可以使用/创建一个Debugger Visualizer,例如几个例子 可用here

罢工之子 Microsoft提供称为SOS的调试器扩展。这是一个非常强大(虽然经常令人困惑)的扩展,这是诊断“泄漏”的一种很好的方法,更准确地说是对不再需要的对象的不必要的引用。

框架源的符号服务器 遵循这些instructions将允许您逐步完成框架的某些部分的来源。

2010年的变化 Visual Studio 2010中存在一些增强功能和新功能:

tiste

赞同来自:

我经常遇到将通用参数对象持久保存到基类中的视图状态的需要。

public abstract class BaseListControl<ListType,KeyType,ParameterType>
                 : UserControl 
                 where ListType : BaseListType
                 && ParameterType : BaseParameterType, new
{
private const string viewStateFilterKey = "FilterKey";
protected ParameterType Filters
    {
        get
        {
            if (ViewState[viewStateFilterKey] == null)
                ViewState[viewStateFilterKey]= new ParameterType();
return ViewState[viewStateFilterKey] as ParameterType;
        }
        set
        {
            ViewState[viewStateFilterKey] = value;
        }
    }
}
用法:
private void SomeEventHappened(object sender, EventArgs e)
{
    Filters.SomeValue = SomeControl.SelectedValue;
}
private void TimeToFetchSomeData()
{
    GridView.DataSource = Repository.GetList(Filters);
}
这个关于“where ParameterType:BaseParameterType,new”的小技巧是它真正起作用的原因。 在我的基类中使用此属性,我可以自动处理分页,设置过滤器值以过滤网格视图,使排序变得非常简单等。 我只是说仿制药可以成为一个非常强大的野兽。

mnam

赞同来自:

Object.ReferenceEquals方法 确定指定的Object实例是否是同一实例。 参数:
  • objA:System.Object - 要比较的第一个Object。
  • objB:System.Object - 要比较的第二个Object。
例:
 object o = null;
 object p = null;
 object q = new Object();
Console.WriteLine(Object.ReferenceEquals(o, p));
 p = q;
 Console.WriteLine(Object.ReferenceEquals(p, q));
 Console.WriteLine(Object.ReferenceEquals(o, p));
与“==”和“.Equals”的区别: 基本上,对象A的Equals()测试与对象B具有相同的内容。 System.Object.ReferenceEquals()方法总是比较引用。 虽然类可以为等于运算符提供自己的行为 (如下所示),如果调用运算符,则不会调用重定义的运算符 通过对System.Object的引用。 对于字符串,没有什么区别,因为已经重写了==和Equals来比较字符串的内容。 另请参阅this answer到另一个问题(“如何在没有无限递归的情况下检查'=='运算符重载中的空值?”)。

kodit

赞同来自:

这是C#4.0中字符串类的新方法:

String.IsNullOrWhiteSpace(String value)
是时候了。

killo

赞同来自:

我在使用ReSharper时选择了这个: 隐式方法组转换

//If given this:
var myStrings = new List<string>(){"abc","def","xyz"};
//Then this:
myStrings.ForEach(s => Console.WriteLine(s));
//Is equivalent to this:
myStrings.ForEach(Console.WriteLine);
有关更多信息,请参阅“Implicit Method Group Conversion in C#”。

xet

赞同来自:

我喜欢滥用静态模板类不共享静态成员的事实。 当Type实例在编译时已知时,这是一个线程安全(在创建时)和任何Dictionary<Type,...>的廉价替代。

public static class MyCachedData<T>{
    static readonly CachedData Value;
    static MyCachedData(){
       Value=// Heavy computation, such as baking IL code or doing lots of reflection on a type
    }
}
干杯, 弗洛里安

yut

赞同来自:

ContextBoundObject 与.NET事物不同的是C#事物。这是实现DI的另一种方式,尽管它可能很难。你必须继承它,这可能是放弃。 http://msdn.microsoft.com/en-us/library/system.contextboundobject.aspx 当我使用自定义日志记录属性修饰类/方法时,我用它来添加日志记录。

oqui

赞同来自:

关于foreach:它不使用'duck typing',因为鸭子输入IMO指的是运行时检查。它在编译时使用结构类型检查(与标称相反)来检查类型中所需的方法。

lillo

赞同来自:

我学到的一件有趣的事情是框架和C#语言的不同部分是在不同的时间编写的,因此是不一致的。例如,框架本身违反了许多FxCop规则,因为在编写框架时规则并非全部到位。 此外,using语句用于对“范围”进行删除,而不是专门用于处理资源。它是在锁定声明之后编写的。 Eric Gunnerson once mentioned如果使用using语句,那么他们可能不需要编写lock语句(虽然谁知道,也许他们会反正),因为using语句可能已经足够了。

mqui

赞同来自:

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

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

wnatus

赞同来自:

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

// 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;
}

comnis

赞同来自:

下面的一个没有隐藏,但它是非常隐含的。我不知道下面的样本是否已经发布在这里,我看不出有什么好处(可能没有),但我会试着展示一个“怪异”的代码。以下示例通过C#(delegates / anonymous delegates [lambdas])和闭包中的仿函数模拟for语句。其他流程语句如ifif/elsewhiledo/whle也被模拟,但我不确定switch(也许,我太懒了:))。我稍微压缩了示例源代码以使其更清晰。

private static readonly Action EmptyAction = () => { };
private static readonly Func<bool> EmptyCondition = () => { return true; };
private sealed class BreakStatementException : Exception { }
private sealed class ContinueStatementException : Exception { }
private static void Break() { throw new BreakStatementException(); }
private static void Continue() { throw new ContinueStatementException(); }
private static void For(Action init, Func<bool> condition, Action postBlock, Action statement) {
    init = init ?? EmptyAction;
    condition = condition ?? EmptyCondition;
    postBlock = postBlock ?? EmptyAction;
    statement = statement ?? EmptyAction;
    for ( init(); condition(); postBlock() ) {
        try {
            statement();
        } catch ( BreakStatementException ) {
            break;
        } catch ( ContinueStatementException ) {
            continue;
        }
    }
}
private static void Main() {
    int i = 0; // avoiding error "Use of unassigned local variable 'i'" if not using `for` init block
    For(() => i = 0, () => i < 10, () => i++,
        () => {
            if ( i == 5 )
                Continue();
            Console.WriteLine(i);
        }
    );
}
如果我没错,这种方法与函数式编程实践相关。我对吗?

cet

赞同来自:

部分方法 Charlie Calvert explains partial methods on his blog Scott Cate has a nice partial method demo here
  1. 代码生成类(LINQ to SQL,EF)
  2. 中的可扩展性
  3. 如果没有实现,则不会编译到dll中(使用.NET Reflector检查)

est_et

赞同来自:

委托语法已经在C#的连续版本中发展,但我仍然发现它们很难记住。幸运的是,Action<>Func<>代表很容易记住。 例如:

  • Action<int>是一个委托方法,它接受一个int参数并返回void。
  • Func<int>是一个委托方法,不带参数并返回int。
  • Func<int, bool>是一个委托方法,它接受一个int参数并返回一个bool。
这些功能是在.NET框架的3.5版本中引入的。

yeum

赞同来自:

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

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

wsint

赞同来自:

这意味着T必须具有公共无参数构造函数:

 class MyClass<T> where T : new()
 {
}

met

赞同来自:

Or赋值运算符相当不错。你可以这样写:

x |= y
而不是这个:
x = x | y
如果您必须以false开头的变量或属性(示例中为x),但您希望仅在其他值为true时将其更改为某个其他布尔变量/属性的值时,这通常是实用的。

but

赞同来自:

其他一切,加上 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();

sesse

赞同来自:

直到最近,我才开始非常欣赏“使用”块。他们让事情变得更加整洁:)

iullam

赞同来自:

Dictionary.TryGetValue(K键,输出V值) 作为支票和一个进入。而不是;

if(dictionary.ContainsKey(key)) 
{
    value = dictionary[key];
    ...
}
你可以做;
if(dictionary.TryGetValue(key, out value)) 
{ ... }
并且已设置该值。

wfuga

赞同来自:

这是我最近发现的一个有用的:

Microsoft.VisualBasic.Logging.FileLogTraceListener
MSDN Link 这是一个TraceListener实现,它具有许多功能,例如自动日志文件翻转,我以前会使用自定义日志记录框架。好处是它是.NET的核心部分,并与Trace框架集成,因此易于立即使用和使用。 这是“隐藏”的,因为它在Microsoft.VisualBasic程序集中......但您也可以从C#中使用它。

zamet

赞同来自:

刚刚学习了不变性,协方差和逆变的意义后,我发现了将包含在.NET 4.0中的inout泛型修饰符。它们似乎模糊不清,大多数程序员都不会知道它们。 Visual Studio Magazine上有一个article,它讨论了这些关键字及其使用方法。

menim

赞同来自:

这对于数据库应用程序开发人员来说可能是非常基础的,但我花了一些时间才意识到null与DBNull.value不同。 如果要查看数据库记录中的值是否为空,则必须使用DBNull.value。

a_et

赞同来自:

我只想提一下(因为其中的T:struct,其中一个是C#编译器的陷阱)

where T : Enum
不会编译。它抛出错误“约束不能是特殊类'System.Enum'”。

xiste

赞同来自:

在通用代码中使用default关键字来返回类型的默认值。

public class GenericList<T>
{
    private class Node
    {
        //...
public Node Next;
        public T Data;
    }
private Node head;
//...
public T GetNext()
    {
        T temp = default(T);
Node current = head;
        if (current != null)
        {
            temp = current.Data;
            current = current.Next;
        }
        return temp;
    }
}
Another example here

bmagni

赞同来自:

从匿名方法访问局部变量允许您使用新的控制流逻辑来包装任何代码,而不必将该代码分解为另一种方法。在方法内部声明的局部变量在方法中可用,例如此处示例中的endOfLineChar局部变量: http://aaronls.wordpress.com/2010/02/02/retrying-on-exception-conditionally/

zomnis

赞同来自:

我喜欢

#if DEBUG
           //Code run in debugging mode
#else
           //Code run in release mode
#endif

snon

赞同来自:

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

"c:\\program files\\oldway"
@"c:\program file\newway"
@告诉编译器忽略字符串中的任何转义字符。

nquas

赞同来自:

@ Robbie Rocketpants

"but my instincts tell me that this would cut a maximum of two type casts operations down to a maximum of one."
如果您按照示例1中的建议(使用is& as)进行强制转换,则会导致对“is”运算符的2次调用。因为当你执行“c = obj as MyClass”时,首先它在幕后调用“is”,然后如果失败则只返回null。 如果您按照示例2中的建议进行演员表,
c = (MyClass)obj
然后这实际上再次执行“is”操作,然后如果它检查失败,则抛出异常(InvalidCastException)。 所以,如果你想做一个轻量级的动态演员,最好做你提供的第三个例子:
MyClass c;
if (obj is MyClass)
{
    c = obj as MyClass
}
if (c != null)
{
}
VS
MyClass c = obj as MyClass;
if (c != null)
{
}
你可以看到哪个更快,更简洁,更清晰。

nnihil

赞同来自:

如果您尝试从项列表中创建逗号分隔的字符串:

string[] itemList = { "Example 1", "Example 2", "Example 3" };
CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection();
commaStr.AddRange(itemList);
//outputs Example 1,Example 2,Example 3
另请参阅here

jalias

赞同来自:

使用枚举。 将字符串转换为枚举:

enum MyEnum
{
    FirstValue,
    SecondValue,
    ThirdValue
}
string enumValueString = "FirstValue";
MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), enumValueString, true)
  • 我使用它从数据库中的设置表加载我的ASP.NET应用程序中的CacheItemPriority的值,这样我就可以动态地控制缓存(以及其他设置),而无需关闭应用程序。
比较enum类型的变量时,不必转换为int:
MyEnum val = MyEnum.SecondValue;
if (val < MyEnum.ThirdValue)
{
    // Do something
}

eipsum

赞同来自:

truefalse运算符真的很奇怪。 可以找到更全面的示例here。 编辑:有相关的问题What’s the false operator in C# good for?

umodi

赞同来自:

  1. 我还无法发表评论,但请注意,默认情况下,Visual Studio 2008会自动切换属性,因此在这种情况下不再需要DebuggerStepThrough属性。
  2. 另外,我没有注意到有人展示如何声明一个无参数的lambda(对于实现Action<>非常有用) () => DoSomething(x);
你还应该阅读关闭 - 我不够聪明,无法正确解释它们。但基本上它意味着编译器会做一些聪明的事情,以便即使在创建lambda之后它超出范围,代码行中的x仍然可以工作。
  1. 我最近也发现你可以假装忽略一个lambda参数: (e, _) => DoSomething(e)
它并不是真的忽略它,只是_是一个有效的标识符。所以你不能忽略这两个参数,但我认为它是一种巧妙的方式来表明我们不关心那个参数(通常是EventArgs,它是.Empty)。

est_et

赞同来自:

我认为如果你必须使用可空类型,最好使用Nullable< .T>而不是问号符号。令人惊讶的是,魔法正在发生。 不知道为什么有人会想要使用Nullable< .bool>。 :-) Krzysztof Cwalina(Framwork Design Guidlines的作者之一)在这里发表了一篇好文章: http://blogs.msdn.com/kcwalina/archive/2008/07/16/Nullable.aspx Mike Hadlow在Nullability Voodoo上有一篇不错的帖子

xiste

赞同来自:

能够使枚举类型具有除int之外的值(默认值)

public enum MyEnum : long
{
    Val1 = 1,
    Val2 = 2
}
此外,您可以为该枚举分配任何数值:
MyEnum e = (MyEnum)123;

asaepe

赞同来自:

Environment.NewLine
用于系统独立的换行符。

ksit

赞同来自:

仅供参考 - 使用扩展方法的枚举二进制操作。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace BinaryOpGenericTest
{
    [Flags]
    enum MyFlags
    {
        A = 1,
        B = 2,
        C = 4
}
static class EnumExtensions
    {
        private static Dictionary<Type, Delegate> m_operations = new Dictionary<Type, Delegate>();
public static bool IsFlagSet<T>(this T firstOperand, T secondOperand) 
                                                  where T : struct
        {
Type enumType = typeof(T);
if (!enumType.IsEnum)
            {
                throw new InvalidOperationException("Enum type parameter required");
            }
Delegate funcImplementorBase = null;
            m_operations.TryGetValue(enumType, out funcImplementorBase);
Func<T, T, bool> funcImplementor = funcImplementorBase as Func<T, T, bool>;
if (funcImplementor == null)
            {
                funcImplementor = buildFuncImplementor(secondOperand);
            }
return funcImplementor(firstOperand, secondOperand);
        }
private static Func<T, T, bool> buildFuncImplementor<T>(T val)
                                                            where T : struct
        {
            var first = Expression.Parameter(val.GetType(), "first");
            var second = Expression.Parameter(val.GetType(), "second");
Expression convertSecondExpresion = Expression.Convert(second, typeof(int));
            var andOperator = Expression.Lambda<Func<T, T, bool>>(Expression.Equal(
                                                                                                       Expression.And(
                                                                                                            Expression.Convert(first, typeof(int)),
                                                                                                             convertSecondExpresion),
                                                                                                       convertSecondExpresion),
                                                                                             new[] { first, second });
            Func<T, T, bool> andOperatorFunc = andOperator.Compile();
            m_operations[typeof(T)] = andOperatorFunc;
            return andOperatorFunc;
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            MyFlags flag = MyFlags.A | MyFlags.B;
Console.WriteLine(flag.IsFlagSet(MyFlags.A));            
            Console.WriteLine(EnumExtensions.IsFlagSet(flag, MyFlags.C));
            Console.ReadLine();
        }
    }
}

oiusto

赞同来自:

新修饰语 在C#中使用“new”修饰符并没有完全隐藏,但它并不常见。当您需要“隐藏”基类成员而不是总是覆盖它们时,new修饰符会派上用场。这意味着当您将派生类强制转换为基类时,“隐藏”方法变为可见,并在派生类中调用而不是相同的方法。 在代码中更容易看到:

public class BaseFoo
{
    virtual public void DoSomething()
    {
        Console.WriteLine("Foo");
    }
}
public class DerivedFoo : BaseFoo
{
    public new void DoSomething()
    {
        Console.WriteLine("Bar");
    }
}
public class DerivedBar : BaseFoo
{
    public override void DoSomething()
    {
        Console.WriteLine("FooBar");
    }
}
class Program
{
    static void Main(string[] args)
    {
        BaseFoo derivedBarAsBaseFoo = new DerivedBar();
        BaseFoo derivedFooAsBaseFoo = new DerivedFoo();
DerivedFoo derivedFoo = new DerivedFoo();
derivedFooAsBaseFoo.DoSomething(); //Prints "Foo" when you might expect "Bar"
        derivedBarAsBaseFoo.DoSomething(); //Prints "FooBar"
derivedFoo.DoSomething(); //Prints "Bar"
    }
}
[艾德:我为双关语获得额外积分吗?对不起,无法帮助。]

bnemo

赞同来自:

我很确定每个人都熟悉运算符重载,但也许有些不是。

class myClass
{
    private string myClassValue = "";
public myClass(string myString)
    {
        myClassValue = myString;
    }
public override string ToString()
    {
        return myClassValue;
    }
public static myClass operator <<(myClass mc, int shiftLen)
    {
        string newString = "";
        for (int i = shiftLen; i < mc.myClassValue.Length; i++)
            newString += mc.myClassValue[i].ToString();
        mc.myClassValue = newString.ToString();
        return mc;
    }
public static myClass operator >>(myClass mc, int shiftLen)
    {
        char[] newString = new char[shiftLen + mc.myClassValue.Length];
for (int i = shiftLen; i < mc.myClassValue.Length; i++)
            newString[i] += mc.myClassValue[i - shiftLen];
mc.myClassValue = new string(newString);
        return mc;
    }
public static myClass operator +(myClass mc, string args)
    {
        if (args.Trim().Length > 1)
            mc.myClassValue += args;
        return mc;
    }
public static myClass operator -(myClass mc, string args)
    {
        if (args.Trim().Length > 1)
        {
            Regex rgx = new Regex(args);
            mc.myClassValue = rgx.Replace(mc.myClassValue, "");
        }
        return mc;
    }
}
我认为能够使用<<左右移动字符串非常酷。和>>或使用 - =删除一组遵循正则表达式模式的字符串
myClass tmpClass = new myClass("  HelloWorld123");
tmpClass -= @"World";
tmpClass <<= 2;
Console.WriteLine(tmpClass);

svelit

赞同来自:

我喜欢关键字continue。 如果你在循环中遇到一个条件并且不想做任何事情而只是推进循环只需坚持“继续;”。 例如。:

foreach(object o in ACollection)
{
  if(NotInterested)
     continue;
}

eut

赞同来自:

Eric Lippert的Four switch oddities

mneque

赞同来自:

在FlagAttribute和enum
中使用“~”运算符 有时我们会使用带有枚举的Flag属性来对枚举执行按位操作。

 [Flags]
 public enum Colors
 {
    None  = 0,
    Red   = 1,
    Blue  = 2,
    White = 4,
    Black = 8,
    Green = 16,
    All   = 31 //It seems pretty bad...
 }
请注意,枚举中选项“All”的值非常奇怪。
而不是我们可以使用标记枚举的“~”运算符。
 [Flags]
 public enum Colors
 {
    None  = 0,
    Red   = 1,
    Blue  = 2,
    White = 4,
    Black = 8,
    Green = 16,
    All   = ~0 //much better now. that mean 0xffffffff in default.
 }

nrerum

赞同来自:

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

__makeref
__reftype
__refvalue
__arglist
这些是未记录的C#关键字(甚至Visual Studio识别它们!),这些关键字是为了在泛型之前更有效的装箱/拆箱而添加的。它们与System.TypedReference结构协同工作。 还有__arglist,用于可变长度参数列表。 人们不太了解的一件事是System.WeakReference - 一个非常有用的类,它跟踪一个对象,但仍然允许垃圾收集器收集它。 最有用的“隐藏”功能是yield return关键字。它并没有真正隐藏,但很多人都不知道。 LINQ建立于此之上;它允许通过在引擎盖下生成状态机来执行延迟执行的查询。 Raymond Chen最近发布了关于internal, gritty details的信息。

xqui

赞同来自:

我能想到的一对夫妇:

[field: NonSerialized()]
public EventHandler event SomeEvent;
这可以防止事件被序列化。 'field:'表示该属性应该应用于事件的支持字段。 另一个鲜为人知的功能是覆盖add / remove事件处理程序:
public event EventHandler SomeEvent
{
    add
    {
        // ...
    }
remove
    {
        // ...
    }
}

eomnis

赞同来自:

Expression Trees怎么样?它们是LINQ的核心,允许延迟执行: 取自David Hayden's blog: 在C#3.0中,您可以使用lambda表达式按如下方式定义委托:

Func<int,int> f = x => x + 1;
此委托在您的应用程序中编译为可执行代码,可以这样调用:
var three = f(2); // 2 + 1
代码按预期工作。这里没什么好看的。 表达树 使用System.Query.Expression将委托定义为表达式树时:
Expression<Func<int,int>> expression = x => x + 1;
委托不再编译为可执行代码,而是编译为可以转换并编译为原始委托的数据。 要在应用程序中实际使用表示为表达式树的委托,您必须在应用程序中编译并调用它:
var originalDelegate = expression.Compile();
var three = originalDelegate.Invoke(2);

oautem

赞同来自:

您可以使用扩展方法创建委托,就像它们是常规方法一样,从而调整this参数。例如,

static class FunnyExtension {
    public static string Double(this string str) { return str + str; }
    public static int Double(this int num) { return num + num; }
}
Func<string> aaMaker = "a".Double;
Func<string, string> doubler = FunnyExtension.Double;
Console.WriteLine(aaMaker());       //Prints "aa"
Console.WriteLine(doubler("b"));    //Prints "bb"
请注意,这不适用于扩展的扩展方法 值类型;请参阅this question

ut_et

赞同来自:

Not sure why anyone would ever want to use Nullable<bool> though. :-)
是的,是的,FileNotFound

prerum

赞同来自:

我认为C#(.NET 3.5)最不受欢迎和鲜为人知的功能之一是Expression Trees,特别是与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的一个重要原因。

gsint

赞同来自:

C#中的指针。 它们可用于执行就地字符串操作。这是一个不安全的功能,因此unsafe关键字用于标记不安全代码的区域。另请注意固定关键字如何用于指示指向的内存是固定的,并且不能由GC移动。这是指向内存地址的指针必不可少的,GC可以将内存移动到不同的地址,否则会导致指针无效。

    string str = "some string";
    Console.WriteLine(str);
    unsafe
    {
        fixed(char *s = str)
        {
            char *c = s;
            while(*c != '\0')
            {
                *c = Char.ToUpper(*c++);                    
            }
        }
    }
    Console.WriteLine(str);
我不会这样做,只是为了这个问题来证明这个功能。

laut

赞同来自:

允许带有大括号的空块。 你可以写这样的代码

{
    service.DoTonsOfWork(args);
}
如果您想尝试没有已经写过的usingtry... finally,那么它会很有用。
//using(var scope = new TransactionScope)
{
    service.DoTonsOfWork(args);
}

esaepe

赞同来自:

Exception Filters。所以“隐藏”你甚至不能使用它们(至少从C#开始)没有后编译补丁;)

zomnis

赞同来自:

我不认为有人提到追加?在值类型名称之后将使其可为空。 你可以做:

DateTime? date = null;
DateTime是一个结构。

wab

赞同来自:

我喜欢使用@字符进行SQL查询。它使sql保持良好和格式化,而不必用字符串分隔符包围每一行。

string sql = @"SELECT firstname, lastname, email
               FROM users
               WHERE username = @username AND password = @password";

menim

赞同来自:

string.Format()中的宽度

Console.WriteLine("Product: {0,-7} Price: {1,5}", product1, price1);
Console.WriteLine("Product: {0,-7} Price: {1,5}", product2, price2);
产生 alt text 来自Prabir's Blog | Hidden C# feature

taut

赞同来自:

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

if (x == 1)
{
   x = 2;
}
else
{
   x = 3;
}
可以浓缩为:
x = (x==1) ? 2 : 3;

walias

赞同来自:

我发现令人难以置信的是编译器通过糖代码使用外部变量会遇到什么样的麻烦:

string output = "helo world!";
Action action = () => Console.WriteLine(output);
output = "hello!";
action();
这实际上打印了hello!。为什么?因为编译器为委托创建了一个嵌套类,所有外部变量都有公共字段,并在每次调用委托之前插入设置代码:)以上是代码'reflectored':
Action action;
<>c__DisplayClass1 CS$<>8__locals2;
CS$<>8__locals2 = new <>c__DisplayClass1();
CS$<>8__locals2.output = "helo world!";
action = new Action(CS$<>8__locals2.<Main>b__0);
CS$<>8__locals2.output = "hello!";
action();
我觉得很酷。

funde

赞同来自:

Yield关键字在具有很大功率时经常被忽略。我之前在博客上讨论了它并讨论了好处(不同的处理),并在收益率的引导下发生,以帮助提供更强的理解。 Using Yield in C#

snon

赞同来自:

类似JavaScript的匿名内联函数 返回一个字符串:

var s = new Func<String>(() =>
{
    return "Hello World!";
})();
返回一个更复杂的对象:
var d = new Func<Dictionary<Int32, String>>(() =>
{
    return new Dictionary<Int32, String>
    {
        { 0, "Foo" },
        { 1, "Bar" },
        { 2, "..." }
    };
})();
一个真实的用例:
var tr = new TableRow();
tr.Cells.AddRange
(
    new[]
    {
        new TableCell { Text = "" },
        new TableCell { Text = "" },
        new TableCell { Text = "" },
new TableCell
        {
            Text = new Func<String>(() =>
            {
                return @"Result of a chunk of logic, without having to define
                         the logic outside of the TableCell constructor";
            })()
        },
new TableCell { Text = "" },
        new TableCell { Text = "" }
    }
);
注意:您不能在内联函数的范围内重用变量名。
替代语法
// The one-liner
Func<Int32, Int32, String> Add = (a, b) => Convert.ToString(a + b);
// Multiple lines
Func<Int32, Int32, String> Add = (a, b) =>
{
    var i = a + b;
return i.ToString();
};
// Without parameters
Func<String> Foo = () => "";
// Without parameters, multiple lines
Func<String> Foo = () =>
{
    return "";
};
缩短字符串并添加水平省略号...
Func<String, String> Shorten = s => s.Length > 100 ? s.Substring(0, 100) + "&hellip;" : s;

ererum

赞同来自:

__arglist也是

[DllImport("msvcrt40.dll")]
public static extern int printf(string format, __arglist);
static void Main(string[] args)
{
   printf("Hello %s!\n", __arglist("Bart"));
}

uet

赞同来自:

通用约束:

 //Constructor constraint, T has a default empty constructor
class Node<K,T> where T : new() 
{
}
//Reference\Value Type constraints
//T is a struct
public class MyClass<T> where T : struct
{...}
//T is a reference type
public class MyClass<T> where T : class
{...}
public class MyClass<T> where T : SomeBaseClass, ISomeInterface
{...}

bsequi

赞同来自:

它实际上并不是一个C#隐藏功能,但我最近发现了WeakReference class并被它所震撼(虽然这可能会因为它帮助我找到particular problem of mine的解决方案而有所偏差...)

quo_et

赞同来自:

Math.Max和Min检查边界: 我在很多代码中看到过这个:

if (x < lowerBoundary) 
{
   x = lowerBoundary;
}
我觉得这个更小,更干净,更易读:
x = Math.Max(x, lowerBoundary);
或者您也可以使用三元运算符:
x = ( x < lowerBoundary) ? lowerBoundary : x;

ramet

赞同来自:

我看到很多人复制了Nullable<T>.GetValueOrDefault(T)的功能。

oalias

赞同来自:

当从可以为空的数据库中检索值并将值重新放入时,可以为空的布尔值非常有用。有时您想知道该字段尚未设置。

ueaque

赞同来自:

没有特别的顺序:

Lists<>
Mutex
Framework 3.5中的新属性定义快捷方式。

liste

赞同来自:

我刚刚学到的一个是你仍然可以调用methods on a nullable value .... 当你有一个可以为空的值时,结果是什么:

decimal? MyValue = null;
您可能认为必须写的地方:
MyValue == null ? null : MyValue .ToString()
你可以写:
MyValue.ToString()
我已经知道我可以调用MyValue.HasValue和MyValue.Value ......但它没有完全点击我可以调用ToString()。

oiusto

赞同来自:

从C / C++迁移的程序员可能会错过这个: 在C#中,%(模数运算符)适用于浮点数!

zquia

赞同来自:

任意嵌套范围{}

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-statement”。
var somePerson = this.GetPerson();  // whatever 
{ 
    var p = somePerson; 
    p.FirstName = "John"; 
    p.LastName = "Doe"; 
    //... 
    p.City = "Gotham"; 
} 
对于挑剔的程序员。

krerum

赞同来自:

如果方法参数实现两个接口,则可以使用泛型来检查(编译时):

interface IPropA 
{
    string PropA { get; set; } 
}
interface IPropB 
{
    string PropB { get; set; }
}
class TestClass 
{
    void DoSomething<T>(T t) where T : IPropA, IPropB 
    {
        MessageBox.Show(t.PropA);
        MessageBox.Show(t.PropB);
    }
}
与从基类和接口继承的参数相同。

gminus

赞同来自:

IEnumerableSelectMany,它将列表列表展平为单个列表。假设我有一个Orders列表,每个Order都有一个LineItems列表。 我想知道出售的LineItems的总数...

int totalItems = Orders.Select(o => o.LineItems).SelectMany(i => i).Sum();

tmodi

赞同来自:

我错过了很长一段时间的东西: 你可以比较字符串

"string".equals("String", StringComparison.InvariantCultureIgnoreCase)
而不是做:
"string".ToLower() == "String".ToLower();

a_et

赞同来自:

文字可以用作该类型的变量。 例如。

Console.WriteLine(5.ToString());
Console.WriteLine(5M.GetType());   // Returns "System.Decimal"
Console.WriteLine("This is a string!!!".Replace("!!", "!"));
只是一点点琐事...... 人们没有提到过很多东西,但它们主要与不安全的构造有关。以下是“常规”代码可以使用的代码: 选中/未选中的关键字:
public static int UncheckedAddition(int a, int b)
{
    unchecked { return a + b; }
}
public static int CheckedAddition(int a, int b)
{
    checked { return a + b; } // or "return checked(a + b)";
}
public static void Main() 
{
    Console.WriteLine("Unchecked: " + UncheckedAddition(Int32.MaxValue, + 1));  // "Wraps around"
    Console.WriteLine("Checked: " + CheckedAddition(Int32.MaxValue, + 1));  // Throws an Overflow exception
    Console.ReadLine();
}

id_cum

赞同来自:

如果您希望在调试和释放模式之间有不同的行为,那么预处理器指令可能很有用。 http://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx

vvelit

赞同来自:

更多的运行时功能,但我最近了解到有两个垃圾收集器。工作站gc和服务器gc。 Workstation是客户端版本的Windows的默认设置,但服务器在多核计算机上要快得多。

<configuration>
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration>
小心。服务器gc需要更多内存。

cvelit

赞同来自:

静态构造函数。 实例:

public class Example
{
    static Example()
    {
        // Code to execute during type initialization
    }
public Example()
    {
        // Code to execute during object initialization
    }
}
静态类:
public static class Example
{
    static Example()
    {
        // Code to execute during type initialization
    }
}
MSDN says
A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. It is called automatically before the first instance is created or any static members are referenced.
例如:
public class MyWebService
{
    public static DateTime StartTime;
static MyWebService()
    {
        MyWebService.StartTime = DateTime.Now;
    }
public TimeSpan Uptime
    {
        get { return DateTime.Now - MyWebService.StartTime; }
    }
}
但是,您也可以轻松完成:
public class MyWebService
{
    public static DateTime StartTime = DateTime.Now;
public TimeSpan Uptime
    {
        get { return DateTime.Now - MyWebService.StartTime; }
    }
}
因此,当您确实需要使用静态构造函数时,您将很难找到任何实例。 MSDN提供了有关静态构造函数的有用说明:
  • A static constructor does not take access modifiers or have parameters.
  • A static constructor is called automatically to initialize the class before the first instance is created
    or any static members are referenced.
  • A static constructor cannot be called directly.
  • The user has no control on when the static constructor is executed in the program.
  • A typical use of static constructors is when the class is using a log file and the constructor is used to write
    entries to this file.
  • Static constructors are also useful when creating wrapper classes for
    unmanaged code, when the constructor
    can call the LoadLibrary method.
  • If a static constructor throws an exception, the runtime will not
    invoke it a second time, and the type will remain uninitialized for the
    lifetime of the application domain in which your program is running.
最重要的注意事项是,如果静态构造函数中发生错误,则抛出TypeIntializationException,您无法深入查看有问题的代码行。相反,您必须检查TypeInitializationExceptionInnerException成员,这是具体原因。

et_id

赞同来自:

验证用户输入时,每种基本类型的TryParse方法都很棒。

double doubleValue
if (!Double.TryParse(myDataRow("myColumn"), out doubleValue))
{
    // set validation error
}

jsed

赞同来自:

如果您尝试在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"

eomnis

赞同来自:

如果要阻止垃圾收集器运行对象的终结器,只需使用GC.SuppressFinalize(object);。与此类似,GC.KeepAlive(object);将阻止垃圾收集器通过引用它来收集该对象。不是很常用,至少在我的经验中,但很高兴知道以防万一。

tin

赞同来自:

params关键字,即

public void DoSomething(params string[] theStrings)
{
  foreach(string s in theStrings)
  {
    // Something with the Strings…
  }
}
叫做像
DoSomething(“The”, “cat”, “sat”, “on”, “the” ,”mat”);

kaut

赞同来自:

volatile关键字告诉编译器一个字段可以被多个线程同时修改。

ut_eos

赞同来自:

字典初始化器对于需要对某些数据进行硬编码的快速黑客攻击和单元测试总是很有用。

var dict = new Dictionary<int, string> { { 10, "Hello" }, { 20, "World" } };

wet

赞同来自:

想到@dp AnonCast并决定尝试一下。以下是我提出的可能对某些人有用的内容:

// using the concepts of dp's AnonCast
static Func<T> TypeCurry<T>(Func<object> f, T type)
{
    return () => (T)f();
}
以下是它的使用方法:
static void Main(string[] args)
{
var getRandomObjectX = TypeCurry(GetRandomObject,
        new { Name = default(string), Badges = default(int) });
do {
var obj = getRandomObjectX();
Console.WriteLine("Name : {0} Badges : {1}",
            obj.Name,
            obj.Badges);
} while (Console.ReadKey().Key != ConsoleKey.Escape);
}
static Random r = new Random();
static object GetRandomObject()
{
    return new {
        Name = Guid.NewGuid().ToString().Substring(0, 4),
        Badges = r.Next(0, 100)
    };
}

yalias

赞同来自:

我不宽恕它,但我很惊讶goto仍然是鸭子传入的射弹

wrerum

赞同来自:

在使用linqxml时,我发现这项技术很有趣:

public bool GetFooSetting(XElement ndef){
   return (bool?)ndef.Element("MyBoolSettingValue") ?? true;
}
而不是:
public bool GetFooSetting(XElement ndef){
   return ndef.Element("MyBoolSettingValue") != null ? bool.Parse(ndef.Element("MyBoolSettingValue") ) : true;
}

ueos

赞同来自:

大多数P/Invoke都有点奇怪。 属性示例:

[DllImport ("gdi32.dll")] 
[return : MarshalAs(UnmanagedType.I4)]
[StructLayout(LayoutKind.Sequential)]

dnulla

赞同来自:

已经提到了所有凉爽的附近。不确定这个是否众所周知 C#property / field构造函数初始化:

var foo = new Rectangle() 
{ 
    Fill = new SolidColorBrush(c), 
    Width = 20, 
    Height = 20 
};
这将创建矩形,并设置列出的属性。 我注意到了一些有趣的东西 - 你可以在属性列表的末尾加一个逗号,而不会出现语法错误。所以这也是有效的:
var foo = new Rectangle() 
{ 
    Fill = new SolidColorBrush(c), 
    Width = 20, 
    Height = 20,
};

overo

赞同来自:

通用事件处理程序:

public event EventHandler<MyEventArgs> MyEvent;
这样您就不必一直声明自己的代理,

fomnis

赞同来自:

没有隐藏,但非常整洁。我发现这是一个简单的if-then-else的简洁替代品,只根据条件分配一个值。

string result = 
              i < 2 ?               //question
              "less than 2" :       //answer
              i < 5 ?               //question
             "less than 5":         //answer   
              i < 10 ?              //question
              "less than 10":       //answer
              "something else";     //default answer