C#的隐藏特性?
hidden-features (20)
@告诉编译器忽略字符串中的任何转义字符。
只是想澄清这一个......它没有告诉它忽略转义字符,它实际上告诉编译器将字符串解释为文字。
如果你有
string s = @"cat
dog
fish"
它将实际打印出来(注意它甚至包括用于缩进的空格):
cat
dog
fish
where T : struct
我们,C#开发人员,都知道C#的基础知识。 我的意思是声明,条件,循环,操作符等。
我们中有些人甚至掌握了Generics , 匿名类型 , lambdas , LINQ等等。
但是C#中最隐藏的特性或技巧是什么,甚至连C#粉丝,瘾君子,专家都不知道?
以下是迄今为止显示的功能:
关键词
- Michael Stum的
yield
-
var
by Michael Stum -
using()
kokosusing()
语句 -
readonly
由kokos -
as
迈克斯通 -
as
/由Ed Swangren - /由Rocketpants改进
- 由deathofrats
default
-
global::
由pzycoman -
using()
由AlexCuse块 - 由JakubŠturc
volatile
-
extern alias
由JakubŠturc
属性
- 由Michael Stum创建的
DefaultValueAttribute
- 由DannySmurf
ObsoleteAttribute
的DannySmurf - Stu
DebuggerDisplayAttribute
-
DebuggerBrowsable
和DebuggerStepThrough
by bdukes -
ThreadStaticAttribute
由marxidad -
FlagsAttribute
由Martin Clarke完成 - 由AndrewBurns
ConditionalAttribute
AndrewBurns
句法
-
??
(coalesce kokos )运营商kokos - 尼克贝拉尔迪号码旗帜
-
where T:new
的LarsMæhlum - Keith隐式泛型
- Keith单参数lambdas
- Keith汽车性能
- Keith命名空间别名
- 逐字字符串由@ Patrick
-
enum
值由lfoust - 由marxidad
- marxidad
event
操作员 - 由Portman格式化字符串括号
- xanadont属性访问器可访问性修饰符
- 由JasonS条件(三元)运算符(
?:
JasonS - 经Binoj Antony
checked
和unchecked
操作员 - Flory
implicit and explicit
操作符
语言功能
- Brad Barker的可空类型
- Keith匿名类型
- Judah Himango的
__makeref __reftype __refvalue
__refvalue - 由lomaxx对象初始值lomaxx
- 由David在达科他州格式化字符串
- 通过marxidad扩展方法
- Jon Erickson的
partial
方法 - John Asbeck的预处理指令
- Robert Durgin的
DEBUG
预处理器指令 - 运营商由SefBkn重载
- 键入由chakrit
- 布尔运算符由Rob Gough 带到下一个层次
- 通过价值类型的变量作为接口没有罗马Boiko拳击
- 通过编程方式确定Roman Boiko声明的变量类型
- Chris静态构造函数
- 使用LINQ by roosteronacid更容易在眼睛/浓缩ORM映射
-
__arglist
by Zac Bowling
Visual Studio功能
- Himadri编辑器中选择文本块
- DannySmurf的片段
骨架
- KiwiBastard
TransactionScope
- KiwiBastard
DependantTransaction
KiwiBastard - IainMH
Nullable<T>
- Diago
Mutex
-
System.IO.Path
by ageektrapped -
WeakReference
by Juan Manuel
方法和属性
- 由KiwiBastard
String.IsNullOrEmpty()
方法 -
List.ForEach()
方法 - Will Dean的
BeginInvoke()
,EndInvoke()
方法 -
Nullable<T>.HasValue
和Nullable<T>.Value
属性由Rismo - John Sheehan的
GetValueOrDefault
方法
提示与技巧
- 事件处理程序的好方法由Andreas HR Nilsson提供
- John大写比较
- 通过dp访问匿名类型而不反射
- 一种快速的方式来延迟Will实例化集合属性
- 由roosteronacid的类似JavaScript的匿名内联函数
其他
Not sure why anyone would ever want to use Nullable<bool> though. :-)
True, False, FileNotFound ?
lambdas和类型推理被低估。 Lambdas可以有多个语句,并且它们自动加入兼容的委托对象 (只要确保签名匹配),如下所示:
Console.CancelKeyPress +=
(sender, e) => {
Console.WriteLine("CTRL+C detected!\n");
e.Cancel = true;
};
请注意,我没有new CancellationEventHandler
也不需要指定sender
和e
类型,它们可以从事件中推导出来。 这就是为什么编写整个delegate (blah blah)
不那么麻烦,这也需要您指定参数类型。
Lambdas不需要返回任何东西 ,类型推断在这种情况下非常强大。
顺便说一下,你总是可以返回使Lambdas处于函数式编程意义上的Lambdas 。 例如,下面是一个使lambda处理Button.Click事件的lambda:
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中的指针,我认为这是你应该学习的另一个基本的东西:-)
避免检查空事件处理程序
在声明中为事件添加一个空的委托,在调用它之前始终检查事件是否为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");
}
}
@Ed, I'm a bit reticent about posting this as it's little more than nitpicking. However, I would point out that in your code sample:
MyClass c;
if (obj is MyClass)
c = obj as MyClass
If you're going to use 'is', why follow it up with a safe cast using 'as'? If you've ascertained that obj is indeed MyClass, a bog-standard cast:
c = (MyClass)obj
...is never going to fail.
Similarly, you could just say:
MyClass c = obj as MyClass;
if(c != null)
{
...
}
I don't know enough about .NET's innards to be sure, but my instincts tell me that this would cut a maximum of two type casts operations down to a maximum of one. It's hardly likely to break the processing bank either way; personally, I think the latter form looks cleaner too.
If you're trying to use curly brackets inside a String.Format expression...
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"
Maybe not an advanced technique, but one I see all the time that drives me crazy:
if (x == 1)
{
x = 2;
}
else
{
x = 3;
}
can be condensed to:
x = (x==1) ? 2 : 3;
Returning anonymous types from a method and accessing members without reflection.
// 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;
}
This one is not "hidden" so much as it is misnamed.
A lot of attention is paid to the algorithms "map", "reduce", and "filter". What most people don't realize is that .NET 3.5 added all three of these algorithms, but it gave them very SQL-ish names, based on the fact that they're part of LINQ.
"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
The ability to use LINQ to do inline work on collections that used to take iteration and conditionals can be incredibly valuable. It's worth learning how all the LINQ extension methods can help make your code much more compact and maintainable.
一般属性,但最重要的是DebuggerDisplay 。 节省你的时间。
以下是一些有趣的隐藏C#特性,采用无证C#关键字的形式:
__makeref
__reftype
__refvalue
__arglist
这些都是未公开的C#关键字(甚至Visual Studio可以识别它们!),它们被添加到泛型之前的更高效的装箱/拆箱。 它们与System.TypedReference结构协同工作。
还有__arglist,用于可变长度参数列表。
有一点人们不太了解的是System.WeakReference - 一个非常有用的类,它跟踪一个对象,但仍然允许垃圾收集器收集它。
最有用的“隐藏”功能将是yield return关键字。 这不是真的隐藏,但很多人不知道。 LINQ建立在此之上; 它允许通过在引擎盖下生成状态机来执行延迟执行的查询。 Raymond Chen最近发布了关于内部细节的详细信息 。
别名仿制药:
using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;
它允许你使用ASimpleName
而不是Dictionary<string, Dictionary<string, List<string>>>
。
当你在很多地方使用相同的通用大型复杂事物时使用它。
如果你想在不调用任何finally块或finalizer的情况下退出你的程序,使用FailFast :
Environment.FailFast()
我会想到“ yield ”。 一些像DefaultValueAttribute这样的属性也是我的最爱。
“ var ”关键字更为人所知,但您也可以在.NET 2.0应用程序中使用它(只要您使用.NET 3.5编译器并将其设置为输出2.0代码)似乎并不十分清楚好。
编辑:kokos,谢谢你指出了?? 操作员,这确实非常有用。 由于它对Google来说有点难(因为??只是忽略了),下面是该运算符的MSDN文档页面: ?? ??
我倾向于发现大多数C#开发人员不知道“可空”类型。 基本上,可以有一个空值的原语。
double? num1 = null;
double num2 = num1 ?? -100;
将一个可以为null的double num1设置为null,如果num1为null,则将常量 double num2设置为num1或-100 。
http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx
关于可空类型还有一件事:
DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();
它返回String.Empty。 查看this链接了解更多详情
我最喜欢的技巧是使用null coalesce操作符和括号来为我自动实例化集合。
private IList<Foo> _foo;
public IList<Foo> ListOfFoo
{ get { return _foo ?? (_foo = new List<Foo>()); } }
我认为C#(.NET 3.5)中最受关注和鲜为人知的特性之一是表达式树 , 特别是当与泛型和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的一个重要原因。
泛型类型中的'default'关键字:
T t = default(T);
如果T是引用类型,则返回'null';如果是int,则返回0;如果是boolean,则返回false。
这不是C#本身,但我没有看到任何真正使用System.IO.Path.Combine()
的人。 实际上,整个Path类非常有用,但没有人使用它!
我敢打赌,每个生产应用程序都有以下代码,即使它不应该:
string path = dir + "\\" + fileName;