C#的隐藏功能?
我从这个问题中学到了以下内容后,便想到了这一点:
where T : struct
我们开发人员都知道C#的基础知识。我的意思是声明,条件,循环,运算符等。
我们中有些人甚至掌握了泛型,匿名类型,lambda,LINQ等内容。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
但是,连球迷,瘾君子,专家都几乎不知道的C的最隐藏的功能或者窍门是什么?
关键字词
- 迈克尔·史丹(Michael Stum)的"收益"
- 由Michael Stum设计的
var
- kokos的
using()
声明 - kokos的
readonly
- as as,作者:Mike Stone
- Ed Swangren的
as
/is
- Rocketpants改进了" as" /" is"
- deathofrats的"默认"
- pzycoman的
global ::
- AlexCuse的
using()
块 - 雅各布·图尔克(Jakub?turc)的" volatile"
- 雅各布·图尔克(Jakub?turc)的" extern alias"
属性
- Michael Stum的" DefaultValueAttribute"
- DannySmurf的" ObsoleteAttribute"
- Stu的
DebuggerDisplayAttribute
- bdukes的
DebuggerBrowsable
和DebuggerStepThrough
- marxidad的" ThreadStaticAttribute"
- Martin Clarke的" FlagsAttribute"
- AndrewBurns的" ConditionalAttribute"
句法
- kokos的
??
(coalesce null)运算符 - 尼克·贝拉迪(Nick Berardi)的数字举报
- Lars M?hlum的
where T:new
- Keith的隐式泛型
- Keith的一参数lambda
- Keith的汽车属性
- Keith的命名空间别名
- 逐字字符串文字,带@ by Patrick
- lfoust的" enum"值
- @variablenames由marxidad
- 马克思的"事件"运算符
- 通过波特曼格式化字符串括号
- xanadont的属性访问器可访问性修改器
- JasonS的条件(三元)运算符(
?:
) - Binoj Antony的" checked"和" unchecked"运算符
- Flory的"隐式和显式"运算符
语言功能
- 布拉德·巴克的可空类型
- Keith的匿名类型
- Judah Himango的__makeref __reftype __refvalue
- lomaxx的对象初始化程序
- David在Dakota中格式化字符串
- 扩展方法by marxidad
- 乔恩·埃里克森(Jon Erickson)的"部分"方法
- John Asbeck的预处理程序指令
- Robert Durgin的DEBUG预处理程序指令
- SefBkn的运算符重载
- 通过chakrit键入推断
- Rob Gough将布尔运算符提高到了一个新水平
- 将值类型变量作为接口传递,无需Roman Boiko进行装箱
- 由Roman Boiko以编程方式确定声明的变量类型
- 克里斯的静态构造函数
- 借助公鸡油酸使用LINQ,更容易在眼睛上/浓缩ORM映射
- Zac Bowling的__arglist
Visual Studio功能
- 通过Himadri在编辑器中选择文本块
- DannySmurf的片段
框架
- KiwiBastard的" TransactionScope"
- KiwiBastard的
DependantTransaction
- IainMH的
Nullable <T>
- Diago的" Mutex"
- ageektrapped的" System.IO.Path"
- Juan Manuel的" WeakReference"
方法和性质
- KiwiBastard的
String.IsNullOrEmpty()
方法 - KiwiBastard的
List.ForEach()
方法 - Will Dean的
BeginInvoke()
,EndInvoke()
方法 - Rismo的
Nullable <T> .HasValue
和Nullable <T> .Value
属性 - John Sheehan的
GetValueOrDefault
方法
提示与技巧
- Andreas H.R. Nilsson为事件处理程序提供的一种不错的方法
- John的大写比较
- 访问匿名类型而无需dp的反映
- Will快速实例化集合属性的快速方法
- roosteronacid的类似于JavaScript的匿名内联函数
其他
- netmodules由kokos
- LINQBridge,邓肯·斯马特(Duncan Smart)
- Joel Coehoorn的并行扩展
解决方案
回答
我会想到"收益"。一些属性,例如[DefaultValue()]也是我的最爱。
关键字" var"稍微有点知名,但是我们似乎也可以在.NET 2.0应用程序中使用它(只要我们使用.NET 3.5编译器并将其设置为输出2.0代码即可)出色地。
编辑:kokos,感谢我们指出?运算符,这确实非常有用。由于要对其进行搜索有点困难(因为??只是被忽略了),因此以下是该操作员的MSDN文档页面:??运算子(CReference)
回答
- ?? -合并运算符
- using(statement / directive)-很棒的关键字,它不仅可以用于调用Dispose,还可以用于其他用途
- 只读-应该更多地使用
- netmodules-太糟糕了,Visual Studio不支持
回答
我最喜欢的两个个人收藏夹:
- 片段(特别是对于属性,对于Visual Studio 2008来说更好)
- 过时的属性
回答
老实说,从定义上讲,专家应该知道这些知识。但是要回答问题:内置类型表(CReference)
编译器的数字标记为此而广为人知:
Decimal = M Float = F Double = D // for example double d = 30D;
但是这些更加晦涩:
Long = L Unsigned Long = UL Unsigned Int = U
回答
我很长一段时间都不知道" as"关键字了。
MyClass myObject = (MyClass) obj;
与
MyClass myObject = obj as MyClass;
如果obj不是MyClass,则第二个将返回null,而不是引发类强制转换异常。
回答
- System.Transactions中的TransactionScope和DependentTransaction是在.NET中使用事务处理的一种轻量级方法-它也不仅仅适用于数据库事务
- 我很惊讶地发现String.IsNullOrEmpty是很多开发人员都不知道的东西
- List.ForEach-使用委托方法遍历通用列表
还有更多,但这就是我头脑中三个明显的问题...
回答
属性一般,但最重要的是DebuggerDisplay。节省我们数年。
回答
我倾向于发现大多数开发人员都不了解"可空"类型。基本上,可以具有空值的图元。
double? num1 = null; double num2 = num1 ?? -100;
将可为空的双精度数num1设置为null,然后将常规双精度数num2设置为num1或者-100(如果num1为null)。
http://msdn.microsoft.com/zh-CN/library/1t3y8s4s(VS.80).aspx
关于Nullable类型的另一件事:
DateTime? tmp = new DateTime(); tmp = null; return tmp.ToString();
它是返回String.Empty。检查此链接以获取更多详细信息
回答
我经常遇到需要将通用参数对象持久保留在基类的viewstate中的需求。
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"的小技巧才使它真正起作用。
使用我的基类中的此属性,我可以自动处理分页,设置过滤器值以过滤网格视图,使排序真正容易等。
我真的只是在说,仿制药在错误的手中可以成为一头强大的野兽。
回答
@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的内部知识,但是我的直觉告诉我,这会将最多两种类型的强制转换操作减少到最多一种。几乎不可能以任何一种方式破坏处理银行。就我个人而言,我认为后者看起来也更干净。
回答
其他一切,再加上
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();
回答
这是一个用于正则表达式和文件路径的有用的代码:
"c:\program files\oldway" @"c:\program file\newway"
@告诉编译器忽略字符串中的任何转义字符。
回答
@布拉德·巴克
我认为如果必须使用可为空的类型,则最好使用Nullable <.T>而不是问号表示法。令人眼前一亮的是魔术正在发生。
虽然不确定为什么有人会使用Nullable <.bool>。 :-)
Krzysztof Cwalina(Framwork设计指南的作者之一)在这里有一篇不错的文章:
http://blogs.msdn.com/kcwalina/archive/2008/07/16/Nullable.aspx
迈克·哈德洛(Mike Hadlow)在Nullability Voodoo上有一篇不错的文章
回答
以下是一些有趣的隐藏Cfeature,以未记录的Ckeywords形式出现:
__makeref __reftype __refvalue __arglist
这些是未记录的关键字(甚至Visual Studio都可以识别!),已添加这些关键字以在泛型之前更有效地装箱/取消装箱。它们与System.TypedReference结构协同工作。
还有__arglist,用于可变长度参数列表。
人们不太了解的一件事是System.WeakReference-一个非常有用的类,它可以跟踪对象,但仍允许垃圾收集器对其进行收集。
最有用的"隐藏"功能是yield return关键字。它并不是真正的隐藏,但是很多人对此并不了解。 LINQ基于此构建。它通过在后台生成状态机来允许延迟执行的查询。雷蒙德·陈(Raymond Chen)最近发布了有关内部细节的详细信息。
回答
Not sure why anyone would ever want to use Nullable<bool> though. :-)
是,否,FileNotFound?
回答
没有特别的顺序:
Lists<> Mutex
Framework 3.5中的新属性定义快捷方式。
回答
避免检查空事件处理程序
在声明时向事件添加一个空的委托,从而消除了在调用该事件之前总是检查该事件是否为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的有关此主题的博客文章(以及可能存在的弊端)。
回答
这不是Cper本身,但是我还没有见过真正使用过System.IO.Path.Combine()的人。实际上,整个Path类确实很有用,但是没有人使用它!
我愿意打赌,每个生产应用程序都具有以下代码,即使它不应该具有以下代码:
string path = dir + "\" + fileName;
回答
The @ tells the compiler to ignore any escape characters in a string.
只是想澄清这一点...它并没有告诉它忽略转义字符,它实际上是告诉编译器将字符串解释为文字。
如果你有
string s = @"cat dog fish"
它实际上将打印为(请注意,它甚至包括用于缩进的空格):
cat dog fish
回答
我喜欢的两件事是自动属性,因此我们可以进一步折叠代码:
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()}
回答
基于此线程应命名为"尽管我们认为我们已经了解所有知识,但最近对Cuntil仍然不了解的东西",所以我的个人功能是异步委托。
直到我读了杰夫·里希特(Jeff Richter)的C#/ CLR书(出色的书,每个使用.NET的人都应该阅读它)之前,我不知道我们可以使用BeginInvoke
/EndInvoke
来调用任何委托。我倾向于执行很多ThreadPool.QueueUserWorkItem
调用(我想这很像委托BeginInvoke
在内部执行的操作),但是有时添加标准化的连接/集合模式可能确实有用。
回答
通用类型中的'default'关键字:
T t = default(T);
如果T是引用类型,则结果为" null";如果它是int,则结果为0;如果它是布尔值,则结果为false;
等。
回答
Lambda表达式
Func<int, int, int> add = (a, b) => (a + b);
晦涩的字符串格式
Console.WriteLine("{0:D10}", 2); // 0000000002 Dictionary<string, string> dict = new Dictionary<string, string> { {"David", "C#"}, {"Johann", "Perl"}, {"Morgan", "Python"} }; Console.WriteLine( "{0,10} {1, 10}", "Programmer", "Language" ); Console.WriteLine( "-".PadRight( 21, '-' ) ); foreach (string key in dict.Keys) { Console.WriteLine( "{0, 10} {1, 10}", key, dict[key] ); }
回答
我喜欢我可以使用LINQ在普通的旧.NET 2.0上使用对象的事实(即无需在任何地方都安装.NET 3.5)。我们所需要做的就是实现所有查询运算符的扩展方法,请参见LINQBridge
回答
除了duncansmart的答复,扩展方法也可以在Framework 2.0上使用。只需在System.Runtime.CompilerServices命名空间下添加一个ExtensionAttribute
类,就可以使用扩展方法(当然,仅适用于C3.0)。
namespace System.Runtime.CompilerServices { public class ExtensionAttribute : Attribute { } }
回答
能够具有枚举类型具有除int之外的值(默认值)
public enum MyEnum : long { Val1 = 1, Val2 = 2 }
此外,我们可以为该枚举分配任何数值这一事实:
MyEnum e = (MyEnum)123;
回答
From CLR via C#: When normalizing strings, it is highly recommended that you use ToUpperInvariant instead of ToLowerInvariant because Microsoft has optimized the code for performing uppercase comparisons.
我记得有一次我的同事在比较之前总是将字符串更改为大写。我一直想知道他为什么这样做,因为我觉得先转换为小写字母更"自然"。读完这本书后,我知道为什么了。
回答
我最喜欢的是
global::
关键字,以使用我们的一些第三方代码提供程序来逃避名称空间地狱...
例子:
global::System.Collections.Generic.List<global::System.String> myList = new global::System.Collections.Generic.List<global::System.String>();
回答
直到最近,我才真正开始欣赏"使用"块。他们使事情更加整洁:)
回答
这个名称并没有被"隐藏",而是被错误命名。
人们对算法" map"," reduce"和" filter"给予了极大的关注。大多数人没有意识到的是.NET 3.5添加了所有这三种算法,但是基于它们属于LINQ的事实,它给了它们非常类似于SQL的名称。
"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扩展方法如何帮助使代码更加紧凑和可维护。
回答
从方法返回匿名类型并访问成员而无需进行反思。
// 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; }
回答
还有ThreadStaticAttribute可以使每个线程的静态字段唯一,因此我们可以使用强类型的线程本地存储。
即使扩展方法不是那么秘密(LINQ基于它们),对于实用程序辅助方法,它们的实用性和可读性也可能并不那么明显:
//for adding multiple elements to a collection that doesn't have AddRange //e.g., collection.Add(item1, item2, itemN); static void Add<T>(this ICollection<T> coll, params T[] items) { foreach (var item in items) coll.Add(item); } //like string.Format() but with custom string representation of arguments //e.g., "{0} {1} {2}".Format<Custom>(c=>c.Name,"string",new object(),new Custom()) // result: "string {System.Object} Custom1Name" static string Format<T>(this string format, Func<T,object> select, params object[] args) { for(int i=0; i < args.Length; ++i) { var x = args[i] as T; if (x != null) args[i] = select(x); } return string.Format(format, args); }
回答
I think if you have to use nullable types, it's better to use Nullable<.T> rather than the question mark notation. It makes it eye-achingly obvious that magic is occurring. Not sure why anyone would ever want to use Nullable<.bool> though.
在VB.NET Web服务中,可能无法传递参数(因为合作伙伴的请求不一致或者不可靠),但是必须通过针对所建议类型的验证(" if is search request"的布尔值)。根据"管理层的另一项需求"进行讨论。
...是的,我知道有人认为这不是正确的方法,但是IsSearchRequest As Nullable(Boolean)使我那天晚上迷失了方向!
回答
将@用作关键字的变量名。
var @object = new object(); var @string = ""; var @if = IpsoFacto();
回答
事件实际上是幕后的委托,任何委托对象都可以具有多个添加函数,并可以分别使用+ =和-=运算符从中分离出来。
事件也可以通过添加/删除来控制,类似于get / set,不同之处在于使用+ =和-=时会调用事件:
public event EventHandler SelectiveEvent(object sender, EventArgs args) { add { if (value.Target == null) throw new Exception("No static handlers!"); _SelectiveEvent += value; } remove { _SelectiveEvent -= value; } } EventHandler _SelectiveEvent;
回答
它实际上不是Chidden功能,但我最近发现了WeakReference类并被它吓了一跳(尽管这可能因它帮助我找到了我的一个特定问题的解决方案而产生了偏见。)
回答
我必须承认,我不确定这是否比普通的ASP.NET转发器onItemDatabound强制转换代码好还是坏,但是无论如何,这是我的5美分。
MyObject obj = e.Item.DataItem as MyObject; if(obj != null) { //Do work }
回答
如果我们尝试在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"
回答
几乎所有很酷的地方都被提及。不知道这个人是否众所周知
Cproperty /字段构造函数初始化:
var foo = new Rectangle() { Fill = new SolidColorBrush(c), Width = 20, Height = 20 };
这将创建矩形,并设置列出的属性。
我注意到有趣的是,我们可以在属性列表的末尾使用逗号,而不会出现语法错误。所以这也是有效的:
var foo = new Rectangle() { Fill = new SolidColorBrush(c), Width = 20, Height = 20, };
回答
不是隐藏的,但我认为许多开发人员并未在可为空的类型上使用HasValue和Value属性。
int? x = null; int y; if (x.HasValue) y = x.Value;
回答
@lomaxx我在前一天(同时也学到了技巧)也了解到,现在我们可以在同一属性上具有不同的访问级别:
public string Name { get; private set;}
这样,只有类本身才能设置Name属性。
public MyClass(string name) { Name = name; }
回答
从里克·斯特拉尔(Rick Strahl):
我们可以链接??运算符,以便我们可以进行一系列空比较。
string result = value1 ?? value2 ?? value3 ?? String.Empty;
回答
查理·卡尔维特(Charlie Calvert)在他的博客中解释了部分方法
Scott Cate在这里有一个不错的局部方法演示
- 代码生成类(LINQ to SQL,EF)中的可扩展点
- 如果未实现,则不会编译到dll中(请使用.NET Reflector进行检查)
回答
也许这不是一种先进的技术,但我一直看到的一种使我发疯的方法:
if (x == 1) { x = 2; } else { x = 3; }
可以浓缩为:
x = (x==1) ? 2 : 3;
回答
如果要在"调试"和"发布"模式之间使用不同的行为,预处理器指令可能会很漂亮。
http://msdn.microsoft.com/zh-CN/library/ed8yd1ha.aspx
回答
我看到很多人复制了Nullable <T> .GetValueOrDefault(T)
的功能。
回答
我们键入" prop",然后按两次[TAB],它将为属性生成有用的代码,并可以加快键入速度。
我知道这可以在VS 2005中使用(我使用它),但是在以前的版本中我不知道。
回答
枚举中的FlagsAttribute怎么样?它允许我们执行按位运算...让我永远了解如何在.NET中很好地进行按位运算。
回答
我敢肯定,每个人都熟悉运算符重载,但也许有些不是。
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);
回答
我了解到的一件有趣的事情是,框架和Clanguage的不同部分是在不同的时间编写的,因此不一致。例如,框架本身违反了许多FxCop规则,因为编写框架时这些规则并未全部就绪。
同样,using语句旨在删除"作用域",而不是专门用于处理资源。它是在lock语句之后编写的。埃里克·冈纳森(Eric Gunnerson)曾经提到过这样的观点:如果using语句排在最前面,则他们可能不需要编写lock语句(尽管谁知道,也许他们仍然会写),因为using语句可能已经足够。
回答
@lainMH,
当从数据库中检索可为空的值并将其放回时,可为空的布尔值很有用。有时我们想知道尚未设置该字段。
回答
在阅读有关.NET框架开发的书时。一个很好的建议是不要使用bool来打开或者关闭内容,而应该使用ENums。
使用ENums,我们无需扩展任何代码即可向函数添加新功能,从而为自己提供了一些可扩展性。
回答
C ??空合并运算符-
并不是真正的隐藏,但很少使用。可能是因为许多开发人员在看到有条件的情况下跑了很远吗?运算符,因此他们在看到这一点时会运行两个。用过的:
string mystring = foo ?? "foo was null"
而不是
string mystring; if (foo==null) mystring = "foo was null"; else mystring = foo;
回答
lambda和类型推断被低估了。 Lambda可以具有多个语句,并且它们可以自动兼用作兼容的委托对象(只需确保签名匹配),如下所示:
Console.CancelKeyPress += (sender, e) => { Console.WriteLine("CTRL+C detected!\n"); e.Cancel = true; };
注意,我没有new CancellationEventHandler
,也没有指定sender
和e
的类型,它们是从事件中推断出来的。这就是为什么编写整个`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中的指针,我认为这是我们还应该学习的另一项基本知识:-)
回答
我想到反射树和表情树...
不要错过Cand Jon Skeet的Jeffrey Richter的CLR
请参阅此处以获取一些资源:
http://www.codeproject.com/KB/trace/releasemodebreakpoint.aspx
http://www.codeproject.com/KB/dotnet/Creating_Dynamic_Types.aspx
http://www.codeproject.com/KB/cs/lambdaexpressions.aspx
回答
#if DEBUG预处理程序指令。这对
测试和调试(尽管我通常更喜欢
单元测试路线)。
string customerName = null; #if DEBUG customerName = "Bob" #endif
仅当Visual Studio设置为时,它才会执行代码块。
在"调试"模式下编译。否则,代码块将是
被编译器忽略(在Visual Studio中为灰色)。
回答
我参加这个聚会很晚,所以我的第一选择已经被接受。但是我还没有看到有人提到这个宝石:
.NET Framework的并行扩展
它具有诸如用Parallel.For替换或者使用Parallel.ForEach进行foreach之类的功能
平行样品:
我们认为在一秒钟内可以创建多少个CLR对象?
请参见以下示例:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace ObjectInitSpeedTest { class Program { //Note: don't forget to build it in Release mode. static void Main() { normalSpeedTest(); parallelSpeedTest(); Console.ForegroundColor = ConsoleColor.White; Console.WriteLine("Press a key ..."); Console.ReadKey(); } private static void parallelSpeedTest() { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("parallelSpeedTest"); long totalObjectsCreated = 0; long totalElapsedTime = 0; var tasks = new List<Task>(); var processorCount = Environment.ProcessorCount; Console.WriteLine("Running on {0} cores", processorCount); for (var t = 0; t < processorCount; t++) { tasks.Add(Task.Factory.StartNew( () => { const int reps = 1000000000; var sp = Stopwatch.StartNew(); for (var j = 0; j < reps; ++j) { new object(); } sp.Stop(); Interlocked.Add(ref totalObjectsCreated, reps); Interlocked.Add(ref totalElapsedTime, sp.ElapsedMilliseconds); } )); } // let's complete all the tasks Task.WaitAll(tasks.ToArray()); Console.WriteLine("Created {0:N} objects in 1 sec\n", (totalObjectsCreated / (totalElapsedTime / processorCount)) * 1000); } private static void normalSpeedTest() { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("normalSpeedTest"); const int reps = 1000000000; var sp = Stopwatch.StartNew(); sp.Start(); for (var j = 0; j < reps; ++j) { new object(); } sp.Stop(); Console.WriteLine("Created {0:N} objects in 1 sec\n", (reps / sp.ElapsedMilliseconds) * 1000); } } }
回答
正确和错误的运算符真的很奇怪。
可以在此处找到更全面的示例。
编辑:有一个相关的SO问题Cgood中的错误运算符有什么用?
回答
返回IQueryable投影
protected void LdsPostings_Selecting(object sender, LinqDataSourceSelectEventArgs e) { var dc = new MyDataContext(); var query = dc.Posting.AsQueryable(); if (isCondition1) { query = query.Where(q => q.PostedBy == Username); e.Result = QueryProjection(query); return; } ... if (isConditionN) { query = query.Where(q => q.Status.StatusName == "submitted"); query = query.Where(q => q.ReviewedBy == Username); e.Result = QueryProjection(query); return; } }
而不是多次编码投影,而是创建一个方法:
private IQueryable QueryProjection(IQueryable<Posting> query) { return query.Select(p => new { p.PostingID, p.Category.CategoryName, p.Type.TypeName, p.Status.StatusName, p.Description, p.Updated, p.PostedBy, p.ReviewedBy, }); }
回答
我喜欢对SQL查询使用@字符。它使sql保持良好的格式,并且不必用字符串定界符将每一行括起来。
string sql = @"SELECT firstname, lastname, email FROM users WHERE username = @username AND password = @password";
回答
考虑过@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) }; }
回答
我喜欢在以下列表中查找内容:
bool basketContainsFruit(string fruit) { return new[] { "apple", "orange", "banana", "pear" }.Contains(fruit); }
而不是:-
bool basketContainsFruit(string fruit) { return fruit == "apple" || fruit == "orange" || fruit == "banana" || fruit == "pear"; }
在实践中并没有提出太多建议,但是将项目与搜索主题进行匹配的想法可能确实非常有用+简洁。
回答
System.Diagnostics命名空间中的其他几个属性非常有帮助。
DebuggerBrowsable将允许我们从调试器窗口中隐藏变量(我们将其用于公开属性的所有私有支持变量)。随之而来的是,DebuggerStepThrough使调试器逐步执行该代码,这对于愚蠢的属性非常有用(如果我们可以依赖于C3.0编译器,则应该将其转换为自动属性)。举个例子
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private string nickName; public string NickName { [DebuggerStepThrough] get { return nickName; } [DebuggerStepThrough] set { this.nickName = value; } }
回答
条件属性
允许我们告诉编译器在某些情况下忽略对带有属性标记的方法的调用(#define)。
省略方法调用的事实也意味着不评估其参数。这非常方便,它使我们可以在Debug.Assert()中调用昂贵的验证函数,而不必担心它们会降低发行版本的速度。
回答
Environment.NewLine
用于系统独立的换行符。
回答
嵌套使用语句
通常我们这样做:
StringBuilder sb = new StringBuilder(); using (StringWriter sw = new StringWriter()) { using (IndentedTextWriter itw = new IndentedTextWriter(sw)) { ... } }
但是我们可以这样:
StringBuilder sb = new StringBuilder(); using (StringWriter sw = new StringWriter()) using (IndentedTextWriter itw = new IndentedTextWriter(sw)) { ... }
回答
extern别名关键字用于引用具有相同完全限定类型名称的两个版本的程序集。
回答
PreviousPage属性:
" System.Web.UI.Page表示将控件转移到当前页面的页面。"
这是非常有用的。
回答
验证用户输入时,每种基本类型的TryParse方法都很棒。
double doubleValue if (!Double.TryParse(myDataRow("myColumn"), out doubleValue)) { // set validation error }
回答
Foreach使用Duck Typing
释义或者无耻地从Krzysztof Cwalinas博客上窃取有关此内容。最有趣的琐事比什么都重要。
为了使对象支持foreach,我们不必实现IEnumerable。 IE。这不是一个约束,编译器也不会检查它。检查的是
- 当前带有一个getter的属性,该getter返回一个Object
例如,
class Foo { public Bar GetEnumerator() { return new Bar(); } public struct Bar { public bool MoveNext() { return false; } public object Current { get { return null; } } } } // the following complies just fine: Foo f = new Foo(); foreach (object o in f) { Console.WriteLine("Krzysztof Cwalina's da man!"); }
回答
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)); }}
回答
罗比(Robbie)
"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
然后,此操作实际上再次执行"是"操作,然后,如果未通过该检查,则会引发异常(InvalidCastException)。
因此,如果我们想进行轻量级的动态转换,则最好执行我们提供的第三个示例:
MyClass c; if (obj is MyClass) { c = obj as MyClass } if (c != null) { }
与
MyClass c = obj as MyClass; if (c != null) { }
我们可以看到哪个更快,更简洁和更清晰。
回答
@David在达科他州:
Console.WriteLine( "-".PadRight( 21, '-' ) );
我曾经这样做,直到发现String类具有一个构造函数,该构造函数允许我们以更简洁的方式执行相同的操作:
new String('-',22);
回答
InternalsVisibleTo属性不是一个众所周知的属性,但是在某些情况下可以派上用场。它基本上允许另一个程序集能够访问定义程序集的"内部"元素。
回答
我今天才发现这一点-我已经与Cfor合作了5年!
这是名称空间别名限定符:
extern alias YourAliasHere;
我们可以使用它来加载相同类型的多个版本。这在维护或者升级方案中很有用,在该方案中,类型的更新版本无法在某些旧代码中使用,但是我们需要将其升级到新版本。在命名空间别名限定符上打一下钩,编译器将让我们在代码中同时拥有这两种类型。
回答
我喜欢关键字"继续"。
如果我们在循环中遇到某个条件,并且除了推进循环之外不执行任何其他操作,只需坚持" continue;"即可。
例如。:
foreach(object o in ACollection) { if(NotInterested) continue; }
回答
不是特定于C的东西,但我是三元运算迷。
代替
if (boolean Condition) { //Do Function } else { //Do something else }
你可以使用简洁
booleanCondtion ? true operation : false operation;
例如
代替
int value = param; if (doubleValue) { value *= 2; } else { value *= 3; }
你可以输入
int value = param * (tripleValue ? 3 : 2);
它确实有助于编写简洁的代码,但是嵌套该死的东西可能是令人讨厌的,并且它们可以用于邪恶,但是我仍然爱那些小傻瓜
回答
看到上面提到了List.ForEach; 2.0引入了一系列基于谓词的集合操作Find,FindAll,Exists等。再加上匿名委托,我们几乎可以实现3.5的lambda表达式的简单性。
回答
我喜欢的几件事:
-如果我们创建类似于以下内容的界面
public interface SomeObject<T> where T : SomeObject<T>, new()
我们可以强制从该接口继承的任何内容
包含无参数的构造函数。这对于
我碰到的几件事。
-使用匿名类型即时创建有用的对象:
var myAwesomeObject = new {Name="Foo", Size=10};
-最后,许多Java开发人员都熟悉如下语法:
public synchronized void MySynchronizedMethod(){}
但是,在Cthis中,语法无效。解决方法是方法属性:
[MethodImpl(MethodImplOptions.Synchronized)] public void MySynchronizedMethod(){}
回答
我认为C(.NET 3.5)的最不被人了解和鲜为人知的功能之一是表达式树,尤其是在与泛型和Lambda结合使用时。这是一种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); } }
这是我现在爱上Lambda和Expression Trees的重要原因之一。
回答
我最喜欢的技巧是使用null合并运算符和括号自动为我实例化集合。
private IList<Foo> _foo; public IList<Foo> ListOfFoo { get { return _foo ?? (_foo = new List<Foo>()); } }
回答
volatile关键字,用于告诉编译器一个字段可以被多个线程同时修改。
回答
我看不到上面的那个,直到最近我才意识到你不能做的是从另一个调用一个构造函数:
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; }
回答
- 我无法发表评论,但是请注意,默认情况下,Visual Studio 2008会自动跳过属性,因此在这种情况下,不再需要DebuggerStepThrough属性。
- 另外,我还没有注意到有人展示了如何声明一个无参数的lambda(可用于实现Action <>)
()=> DoSomething(x);
我们还应该阅读有关闭包的知识,我不够聪明,无法正确解释它们。但是从根本上讲,这意味着编译器会做一些聪明的事情,以便即使在创建lambda之后"超出范围",该行代码中的x仍然可以工作。
- 最近我还发现,我们可以假装忽略lambda参数:((e,_)=> DoSomething(e)`
并不是真的忽略它,只是_是有效的标识符。因此,我们不能忽略这样的两个参数,但是我认为这是一种表明我们不在乎该参数(通常是EventArgs,即.Empty)的巧妙方法。
回答
System.Runtime.Remoting.Proxies.RealProxy
它可以在C#中启用面向方面的编程,并且我们还可以使用它进行很多其他花哨的工作。
回答
别名泛型:
using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;
它允许我们使用" ASimpleName",而不是" Dictionary <string,Dictionary <string,List <string >>>"。
当我们在许多地方使用相同的通用大型长复杂事物时,请使用它。
回答
新修饰符
在Cis中"新"修饰符的用法不是完全隐藏的,但它并不经常出现。当我们需要"隐藏"基类成员而不总是覆盖它们时,新修饰符会派上用场。这意味着,当我们将派生类强制转换为基类时,"隐藏"方法将变为可见状态,并被调用,而不是派生类中的相同方法。
在代码中更容易看到:
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" } }
[Ed:双关语能为我加分吗?抱歉,没有帮助。]
回答
不要忘记goto。
回答
可以通过在case中没有代码(请参见case 0)或者使用特殊的goto case(请参见case 1)或者goto default来实现切换。 (请参阅"案例2")表格:
switch (/*...*/) { case 0: // shares the exact same code as case 1 case 1: // do something goto case 2; case 2: // do something else goto default; default: // do something entirely different break; }
回答
#region {string}和#endregion对对代码分组(概述)非常整洁。
#region Using statements using System; using System.IO; using ....; using ....; #endregion
可以将代码块压缩为单个描述文本行。也可以在函数内部工作。
回答
静态构造函数。
实例:
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说:
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",并且我们无法深入到令人讨厌的代码行。相反,我们必须检查TypeInitializationException的InnerException成员,这是具体原因。
回答
BCL中的某些并发实用程序可能具有隐藏功能。
诸如System.Threading.Monitor之类的内容在内部由lock关键字使用;显然,在Clock中使用lock关键字是可取的,但有时它需要了解较低级别的工作方式;我必须锁定C ++ / CLI,因此我将对Monitor.Enter()和Monitor.Exit()的调用封装在代码块中。
回答
文字可用作该类型的变量。
例如。
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(); }
回答
在lambda发挥作用之前,它是匿名委托。可以将其用于类似于Ruby的块代码的通用代码。我还没有测试过lambda的工作原理,因为到目前为止我仍然想使用.NET 2.0。
例如,当我们要确保记得关闭HTML标签时:
MyHtmlWriter writer=new MyHtmlWriter(); writer.writeTag("html", delegate () { writer.writeTag("head", delegate() { writer.writeTag("title"...); } ) })
我敢肯定,如果lambda是一个选项,则可以产生更简洁的代码:)
回答
如果允许第三方扩展,则必须了解C5和Microsoft CCR(请参阅此博客文章以获取快速介绍)。
C5补充了.Net稍微缺乏的collections库(不是Set ???),而CCR使并发编程更容易(我听说这是由于要与Parallel Extensions合并)。
回答
Dictionary.TryGetValue(K键,输出V值)
可作为支票和一次性票。而不是;
if(dictionary.ContainsKey(key)) { value = dictionary[key]; ... }
你可以做;
if(dictionary.TryGetValue(key, out value)) { ... }
并且该值已设置。
回答
我认为很多人都知道C语言中的指针,但是不确定C语言中的指针是否有效。我们可以在不安全的上下文中使用指针:
static void Main() { int i; unsafe { // pointer pi has the address of variable i int* pi = &i; // pointer ppi has the address of variable pi int** ppi = π // ppi(addess of pi) -> pi(addess of i) -> i(0) i = 0; // dereference the pi, i.e. *pi is i Console.WriteLine("i = {0}", *pi); // output: i = 0 // since *pi is i, equivalent to i++ (*pi)++; Console.WriteLine("i = {0}", *pi); // output: i = 1 // since *ppi is pi, one more dereference *pi is i // equivalent to i += 2 **ppi += 2; Console.WriteLine("i = {0}", *pi);// output: i = 3 } Console.ReadLine(); }
回答
一些 ??怪异:)
Delegate target = (target0 = target as CallTargetWithContext0) ?? (target1 = target as CallTargetWithContext1) ?? (target2 = target as CallTargetWithContext2) ?? (target3 = target as CallTargetWithContext3) ?? (target4 = target as CallTargetWithContext4) ?? (target5 = target as CallTargetWithContext5) ?? ((Delegate)(targetN = target as CallTargetWithContextN));
有趣的是,出于某种原因需要最后一次转换。错误还是设计使然?
回答
System.Diagnostics.Debug.Assert (false);
将触发一个弹出窗口,并允许我们在执行过程中将调试器添加到正在运行的.NET进程。在某些时候由于某些原因而无法直接调试ASP.NET应用程序的情况下非常有用。
回答
有一些运算符用于在声明的类和一个或者多个任意类之间执行"隐式"和"显式"用户定义的类型转换。 "隐式"运算符有效地模拟了赋值运算符的重载,这在C ++之类的语言中却是可能的,但在C#中却没有。
它似乎并不是一个经常遇到的功能,但实际上它已在LINQ to XML(System.Xml.Linq
)库中使用,我们可以在其中隐式将字符串转换为XName
对象。例子:
XName tagName = "x:Name";
我在本文中发现了有关如何在C#中模拟多重继承的功能。
回答
纯净,安全的C#中的并集(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;
回答
我遇到的一些隐藏功能:
stackalloc
,它允许我们在堆栈上分配数组- 没有显式参数列表的匿名方法,这些方法可以隐式转换为具有非out / ref参数的任何委托类型(如前面的注释中所述,对于事件非常方便)
- 很多人不知道真正的事件是什么(一对添加/删除方法,例如属性的get / set); C#中的类似字段的事件实际上声明了一个变量和一个事件
- 可以重载
==
和!=
运算符以返回布尔类型以外的其他类型。奇怪但真实。 - 在某些方面,C#3中的查询表达式转换实际上是"简单的"-这意味着我们可以使它完成一些非常奇怪的事情。
- 可空类型具有特殊的装箱行为:空值将被装箱为空引用,并且我们也可以从空值取消装箱为可空类型。
回答
我在Stack Overflow上仅了解的一项功能是能够在return参数上设置属性。
[AttributeUsage( AttributeTargets.ReturnValue )] public class CuriosityAttribute:Attribute { } public class Bar { [return: Curiosity] public Bar ReturnANewBar() { return new Bar(); } }
对我来说,这确实是一个隐藏的功能:-)
回答
字符串实习。这是我尚未在本次讨论中看到的内容。这有点晦涩,但在某些情况下可能会有用。
CLR保留了对文字字符串(和以编程方式插入的字符串)的引用表。如果在代码的多个位置使用相同的字符串,则它将在表中存储一次。这样可以减轻分配字符串所需的内存量。
我们可以使用String.IsInterned(string)来测试字符串是否被插入,也可以使用String.Intern(string)来插入字符串。
注意:在应用程序甚至AppDomain结束后,CLR可以保留对实习字符串的引用。有关详细信息,请参见MSDN文档。
回答
params关键字,即
public void DoSomething(params string[] theStrings) { foreach(string s in theStrings) { // Something with the Strings… } }
叫像
DoSomething(“The”, “cat”, “sat”, “on”, “the” ,”mat”);
回答
标记我的末端区域...
#region stuff1 #region stuff1a //... #endregion stuff1a #endregion stuff1
回答
我在使用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);
有关更多信息,请参见" C#中的隐式方法组转换"。
回答
我不喜欢使用int.TryParse()或者Convert.ToInt32(),而是喜欢拥有一个静态整数解析函数,该函数在无法解析时会返回null。然后我可以使用??和三元运算符一起使用,以更清楚地确保我的声明和初始化都以一种易于理解的方式在一行上完成。
public static class Parser { public static int? ParseInt(string s) { int result; bool parsed = int.TryParse(s, out result); if (parsed) return result; else return null; } // ... }
这也可以避免重复分配左侧的内容,也可以避免重复长时间复制右侧的长调用,例如下面的示例中的数据库调用。而不是丑陋的if-then树(我经常遇到):
int x = 0; YourDatabaseResultSet data = new YourDatabaseResultSet(); if (cond1) if (int.TryParse(x_input, x)){ data = YourDatabaseAccessMethod("my_proc_name", 2, x); } else{ x = -1; // do something to report "Can't Parse" } } else { x = y; data = YourDatabaseAccessMethod("my_proc_name", new SqlParameter("@param1", 2), new SqlParameter("@param2", x)); }
你可以做:
int x = cond1 ? (Parser.ParseInt(x_input) ?? -1) : y; if (x >= 0) data = YourDatabaseAccessMethod("my_proc_name", new SqlParameter("@param1", 2), new SqlParameter("@param2", x));
更清洁,更容易理解
回答
Environment.UserInteractive属性。
The UserInteractive property reports false for a Windows process or a service like IIS that runs without a user interface. If this property is false, do not display modal dialogs or message boxes because there is no graphical user interface for the user to interact with.
回答
ContextBoundObject
与其说是.NET,还不如说是Cthing。尽管可能很辛苦,但这是实现DI的另一种方法。而且我们必须从它那里继承下来,而这可能会推迟。
http://msdn.microsoft.com/zh-CN/library/system.contextboundobject.aspx
当我使用自定义日志记录属性装饰类/方法时,已使用它来添加日志记录。
回答
完全访问调用堆栈:
public static void Main() { StackTrace stackTrace = new StackTrace(); // get call stack StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) // write call stack method names foreach (StackFrame stackFrame in stackFrames) { Console.WriteLine(stackFrame.GetMethod().Name); // write method name } }
因此,如果我们要使用第一个功能,那么我们将知道所使用的功能。如果要创建帮助程序跟踪功能,请在最后一个功能之前使用一个功能,这样我们就会知道调用者。
回答
在使用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; }
回答
如果要退出程序而不调用任何finally块或者终结器,请使用FailFast:
Environment.FailFast()
回答
double dSqrd = Math.Pow(d,2.0);
比
double dSqrd = d * d; // Here we can lose precision
回答
我们可以打开字符串!
switch(name) { case "Dave": return true; case "Bob": return false; default: throw new ApplicationException(); }
非常便利!比一堆if-else语句干净得多
回答
刚刚了解到,匿名类型可以从变量名称推断出属性名称:
string hello = "world"; var o = new { hello }; Console.WriteLine(o.hello);
回答
更多的是运行时功能,但是我最近了解到有两个垃圾收集器。工作站gc和服务器gc。 Windows客户端版本上的默认工作站是Workstation,但多核计算机上的服务器要快得多。
<configuration> <runtime> <gcServer enabled="true"/> </runtime> </configuration>
当心。服务器gc需要更多内存。
回答
对于数据库应用程序开发人员来说,这可能是非常基本的,但是花了我一段时间才意识到null与DBNull.value不同。
要查看数据库记录中的值是否为空时,必须使用DBNull.value。
回答
Object.ReferenceEquals方法
确定指定的Object实例是否为同一实例。
参数:
- objA:System.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));
与" =="和"。等于"的区别:
基本上,对象A的Equals()测试具有与对象B相同的内容。
方法System.Object.ReferenceEquals()始终比较引用。
尽管类可以为相等运算符提供其自己的行为
(如下),如果调用了重新定义的运算符,则不会调用该运算符
通过对System.Object的引用。
对于字符串而言,实际上并没有什么区别,因为==和Equals均已被覆盖以比较字符串的内容。
另请参见另一个问题的答案("如何在没有无限递归的情况下检查==运算符重载中的空值?")。
回答
Mixins。基本上,如果要向多个类添加功能,但不能对所有这些类都使用一个基类,请获取每个类以实现一个接口(无成员)。然后,为接口编写扩展方法,即
public static DeepCopy(this IPrototype p) { ... }
当然,牺牲了一些清晰度。但这有效!
回答
ThreadStaticAttribute是我的最爱。另外,NonSerializableAttribute很有用。 (我们能告诉我使用远程处理很多服务器工作吗?)
回答
通用事件处理程序:
public event EventHandler<MyEventArgs> MyEvent;
这样,我们不必一直声明自己的代表,
回答
刚刚从尝试与定义了不带__stdcall的回调的非托管C ++函数库对接中学习了[UnmanagedFunctionPointerAttribute(CallingConvention.CDecl)]的乐趣。
回答
我将近一年没有发现强类型DataRows包含Is [ColumnName] Null()方法。
例如:
Units.UnitsDataTable dataTable = new Units.UnitsDataTable(); foreach (Units.UnitsRow row in dataTable.Rows) { if (row.IsPrimaryKeyNull()) //.... if (row.IsForeignKeyNull()) //.... }
回答
Math.Max和Min检查边界:
我已经在很多代码中看到了这一点:
if (x < lowerBoundary) { x = lowerBoundary; }
我发现它更小,更干净,更易读:
x = Math.Max(x, lowerBoundary);
或者,我们也可以使用三元运算符:
x = ( x < lowerBoundary) ? lowerBoundary : x;
回答
我很想念的东西:
"string".equals("String", StringComparison.InvariantCultureIgnoreCase)
我们可以将字符串与
"string".ToLower() == "String".ToLower();
回答
而不是做:
internal interface IPrototype<T> { }
Mixins是一个不错的功能。基本上,mixin允许我们使用接口而不是类的具体代码。然后,只需在一系列类中实现该接口,即可自动获得mixin功能。例如,要将深度复制混入几个类中,请定义一个接口
internal static class Prototype { public static T DeepCopy<T>(this IPrototype<T> target) { T copy; using (var stream = new MemoryStream()) { var formatter = new BinaryFormatter(); formatter.Serialize(stream, (T)target); stream.Seek(0, SeekOrigin.Begin); copy = (T) formatter.Deserialize(stream); stream.Close(); } return copy; } }
为此接口添加功能
回答
然后以任何类型实现接口以获取混合。
ViewState吸气剂可以是单线的。
public string Caption { get { return (string) (ViewState["Caption"] ?? "Foo"); } set { ViewState["Caption"] = value; } } public int Index { get { return (int) (ViewState["Index"] ?? 0); } set { ViewState["Index"] = value; } }
使用默认值:
public string Caption { get { return (string) ViewState["Caption"]; } set { ViewState["Caption"] = value; } } public int? Index { get { return (int?) ViewState["Index"]; } set { ViewState["Index"] = value; } }
使用null作为默认值:
回答
这适用于字典支持的任何东西。
回答
关于" foreach":它不使用"鸭子类型",因为鸭子类型IMO指的是运行时检查。它在编译时使用结构类型检查(而不是标称值)来检查类型中所需的方法。
回答
这是有关如何使用#Region指令记录代码的提示。
try { return _field; } finally { _field = null; }
回答
(我只是用过这个)将字段设置为null并返回它而没有中间变量:
回答
显式接口成员实现,其中实现了接口成员,但是除非实例强制转换为接口类型,否则该接口成员将隐藏。
public StringBuilder Builder { get { return _builder ?? (_builder = new StringBuilder()); } }
一行中的按需字段初始化:
回答
我不确定我对C支持赋值表达式的感觉,但是,嘿,它在那里:-)
using(new CursorState(this, BusyCursor)); { // Do stuff }
有几个人提到使用块,但是我认为它们比人们意识到的有用得多。将它们视为穷人的AOP工具。我有许多简单的对象,它们可以在构造函数中捕获状态,然后在Dispose()方法中将其还原。这使我可以将一个功能包装在using块中,并确保在最后恢复状态。例如:
回答
CursorState捕获表单正在使用的当前游标,然后将表单设置为使用提供的游标。最后,它将恢复原始光标。我做了很多这样的事情,例如在刷新之前捕获选择和网格上的当前行,等等。
public class MyClass { public string H?rf?ner() { return "Yes, it works!"; } }
我们可以在Cnames中使用任何Unicode字符,例如:
public class MyClass { public string H\u00e5rf?ner() { return "Yes, it (still) works!"; } }
回答
我们甚至可以使用Unicode转义。这相当于上面的内容:
#if DEBUG Console.Write("Debugging"); #else Console.Write("Final"); #endif
怎么使用这个:
使用定义的DEBUG编译解决方案后,它将输出" Debugging"。
回答
如果编译设置为"释放",它将写入"最终"。
框架功能
回答
我不知道,但是我对VisualStyleRenderer和整个System.Windows.Forms.VisualStyles-Namespace感到非常惊讶。太酷了!
IEnumerable的SelectMany,它将列表的列表展平为一个列表。假设我有一个"订单"列表,每个"订单"都有该订单上的" LineItems"列表。
int totalItems = Orders.Select(o => o.LineItems).SelectMany(i => i).Sum();
回答
我想知道售出的LineItems总数...
这不是Cspecific类型,但我刚刚找到了ISurrogateSelector和ISerializationSurrogate接口-
http://msdn.microsoft.com/zh-CN/library/system.runtime.serialization.isurrogateselector.aspx
http://msdn.microsoft.com/zh-CN/library/system.runtime.serialization.isurrogateselector.aspx
将它们与BinaryFormatter结合使用,可以通过代理类的实现将不可序列化的对象序列化。代理模式在计算机科学中是很容易理解的,尤其是在处理序列化问题时。我认为这个实现只是作为BinaryFormatter的构造函数的参数而被隐藏起来,这太糟糕了。
回答
仍然非常隐藏。 :)
委托语法在C#的后续版本中得到了发展,但是我仍然很难记住它们。幸运的是,Action <>
和Func <>
的代表很容易记住。
- Action <int>是一个委托方法,它采用单个int参数并返回void。
- Func <int>是一个不带任何参数并返回一个int的委托方法。
- Func <int,bool>是一个委托方法,它接受单个int参数并返回bool。
例如:
回答
这些功能是在.NET Framework 3.5版中引入的。
bool myFlag = System.Xml.XmlConvert.ToBoolean(myAttribute.Value);
我喜欢的一个很棒的类是System.Xml.XmlConvert
,可用于从xml标记读取值。特别是,如果我从xml属性或者元素中读取布尔值,则使用
回答
注意:由于xml中的布尔类型除了接受" true"和" false"作为有效值外,还接受1和0,因此在这种情况下使用字符串比较容易出错。
short x = 32767; // 32767 is the max value for short short y = 32767; int z1 = checked((short)(x + y)); //will throw an OverflowException int z2 = unchecked((short)(x + y)); // will return -2 int z3 = (short)(x + y); // will return -2
回答
其他未充分使用的运算符为"已检查"和"未检查":
class ClassA { public ClassA(int a) { //Do something } public void Method1() { //Do Something } } class ClassB : ClassA { public ClassB(int a) : base(a) // calling the base class constructor { //Do something } public void Method2() { base.Method1(); // calling the base class method } }
要调用基类构造函数,只需将base()与构造函数内联。
要调用基类方法,我们可以将base.MethodName()放在派生类方法中
回答
当然,我们可以只说base.MethodName()
来调用基类的方法。
C4.0中的动态关键字
dynamic invoker=new DynamicInvoker(); dynamic result1=invoker.MyMethod1(); dynamic result2=invoker.MyMethod2();
如果希望只在运行时解析方法调用,则可以使用dynamic关键字。
public class DynamicInvoker : IDynamicObject { public MetaObject GetMetaObject (System.Linq.Expressions.Expression parameter) { return new DynamicReaderDispatch (parameter); } } public class DynamicDispatcher : MetaObject { public DynamicDispatcher (Expression parameter) : base(parameter, Restrictions.Empty){ } public override MetaObject Call(CallAction action, MetaObject[] args) { //You'll get MyMethod1 and MyMethod2 here (and what ever you call) Console.WriteLine("Logic to invoke Method '{0}'", action.Name); return this; //Return a meta object } }
回答
在这里,我实现了一个动态调用程序。
static void Main(string[] args) { var domain = "matrix"; Check(() => domain); Console.ReadLine(); } static void Check<T>(Expression<Func<T>> expr) { var body = ((MemberExpression)expr.Body); Console.WriteLine("Name is: {0}", body.Member.Name); Console.WriteLine("Value is: {0}", ((FieldInfo)body.Member) .GetValue(((ConstantExpression)body.Expression).Value)); } // output: // Name is: 'domain' // Value is: 'matrix'
使用LINQ表达式执行强类型反射的能力:
回答
有关更多详细信息,请参见如何在C#中查找变量或者参数名称?
这不是C特有的功能,但是我发现它是一个非常有用的插件。它称为资源重构工具。它允许我们右键单击文字字符串并将其提取到资源文件中。它将搜索代码并找到匹配的其他文字字符串,并将其替换为Resx文件中的相同资源。
回答
http://www.codeplex.com/ResourceRefactoring
List<int> s = new List<int> { 6, 1, 2 }; bool a = s.TrueForAll(p => p > 0);
回答
闭包
List <T>`的TrueForAll方法:
bool changed = false; if (model.Prop1 != prop1) { changed = true; model.Prop1 = prop1; } if (model.Prop2 != prop2) { changed = true; model.Prop2 = prop2; } // ... etc.
自从匿名委托添加到2.0中以来,我们已经能够开发闭包。它们很少被程序员使用,但是具有诸如立即重用代码之类的巨大好处。考虑这段代码:
bool changed = false; Action<Action> setAndTagChanged = (action) => { changed = true; action(); }; if (model.Prop1 != prop1) setAndTagChanged(() => model.Prop1 = prop1); if (model.Prop2 != prop2) setAndTagChanged(() => model.Prop2 = prop2);
注意,上面的if语句执行相似的代码段,只是一行代码例外,即设置不同的属性。可以使用以下代码来缩短代码长度,在该代码行中,将变化的代码行作为参数输入到"动作"对象(适当命名为" setAndTagChanged")中:
在第二种情况下,闭包允许我们在lambda中定义change
变量的范围,这是解决此问题的简便方法。
private bool conditionalSet(bool condition, Action action) { if (condition) action(); return condition; } // ... bool changed = false; changed |= conditionalSet(model.Prop1 == prop1, () => model.Prop1 = prop1); changed |= conditionalSet(model.Prop2 == prop2, () => model.Prop2 = prop2);
回答
另一种方法是使用另一个未使用的功能,即"或者相等"的二进制赋值运算符。以下代码显示了如何:
我之所以称其为AutoDebug,是因为我们可以根据bool值直接在需要的位置和时间进行调试,该值也可以存储为项目用户设置。
//Place at top of your code public UseAutoDebug = true; //Place anywhere in your code including catch areas in try/catch blocks Debug.Assert(!this.UseAutoDebug);
例子:
只需将以上内容放置在try / catch块或者代码的其他区域中,然后将UseAutoDebug设置为true或者false,然后在我们希望进行测试的任何时间进入调试状态。
我们可以保留此代码,并在测试时打开和关闭此功能,还可以将其保存为项目设置,并在部署后手动更改它,以在需要时(如果需要)从用户那里获取其他错误信息。
我们可以在此处的Visual Studio CProject模板中看到使用该技术的实用且有效的示例,在该模板中使用率很高:
回答
http://code.msdn.microsoft.com/SEHE
interface IFoo<T> { T Bar {get;} } class MyFoo<T> : IFoo<T> { public MyFoo(T t) {Bar = t;} public T Bar {get; private set;} } static class Foo { public static IFoo<T> ToFoo<T>(this T t) {return new MyFoo<T>(t);} public static void Do<T>(this T t, Action<T> a) { a(t);} public static IFoo<U> Select<T,U>(this IFoo<T> foo, Func<T,U> f) { return f(foo.Bar).ToFoo(); } } /* ... */ using (var file = File.OpenRead("objc.h")) { var x = from f in file.ToFoo() let s = new Scanner(f) let p = new Parser {scanner = s} select p.Parse(); x.Do(p => { /* drop into imperative code to handle file in Foo monad if necessary */ }); }
回答
C3.0的LINQ查询理解是一种完整的Monadic理解,属于Haskell(实际上,它们是由Haskell的一位设计师设计的)。它们适用于遵循" LINQ模式"的任何泛型类型,并允许我们以纯一元函数式的样式编写,这意味着所有变量都是不可变的(好像我们使用的唯一变量是IDisposables和
IEnumerable的using和foreach语句)。这有助于使变量声明靠近使用它们的位置,并确保所有副作用(如果有的话)都已明确声明。
[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)) { ... }
我想说使用某些系统类作为扩展方法非常方便,例如System.Enum,我们可以执行以下操作...
回答
这仅是示例,当然这些方法可能需要更多的工作...
回答
我们可以在非泛型类中使用泛型方法。
(_, b, __) => b.DoStuff(); // only interested in b here
回答
使用lambdas时模拟功能性"通配符"参数(例如Haskell中的" _")的绝妙技巧:
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(); } } }
回答
仅供参考使用扩展方法的枚举二进制操作。
方法组不是很清楚。
Func<Func<int,int>,int,int> myFunc1 = (i, j) => i(j); Func<int, int> myFunc2 = i => i + 2;
鉴于:
var x = myFunc1(myFunc2, 1);
你可以这样做:
var x = myFunc1(z => myFunc2(z), 1);
回答
代替这个:
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); } }
我们可以使用泛型来检查(编译时)方法参数是否实现了两个接口:
回答
与从基类和接口继承的参数相同。
namespace constructorChain { using System; public class Class1 { public string x; public string y; public Class1() { x = "class1"; y = ""; } public Class1(string y) : this() { this.y = y; } } public class Class2 : Class1 { public Class2(int y) : base(y.ToString()) { } } }
是否已引用构造函数链?
constructorChain.Class1 c1 = new constructorChain.Class1(); constructorChain.Class1 c12 = new constructorChain.Class1("Hello, Constructor!"); constructorChain.Class2 c2 = new constructorChain.Class2(10); Console.WriteLine("{0}:{1}", c1.x, c1.y); Console.WriteLine("{0}:{1}", c12.x, c12.y); Console.WriteLine("{0}:{1}", c2.x, c2.y); Console.ReadLine();
回答
...
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
回答
没有隐藏,但是很整洁。我发现这是一个简单的if-then-else的替代方法,该if-then-else仅根据条件分配值。
Microsoft.VisualBasic.Logging.FileLogTraceListener
这是我最近发现的一个有用的东西:
MSDN链接
这是一个TraceListener实现,具有很多功能,例如自动日志文件翻转,我以前会使用自定义日志记录框架。令人高兴的是它是.NET的核心部分,并且与Trace框架集成在一起,因此很容易立即使用。
回答
这是"隐藏的",因为它在Microsoft.VisualBasic程序集中...但是我们可以从Cas很好地使用它。
使用枚举。
enum MyEnum { FirstValue, SecondValue, ThirdValue } string enumValueString = "FirstValue"; MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), enumValueString, true)
- 我用它来从数据库的设置表中加载ASP.NET应用程序中CacheItemPriority的值,这样我就可以动态控制缓存(以及其他设置)而无需关闭应用程序。
将字符串转换为枚举:
MyEnum val = MyEnum.SecondValue; if (val < MyEnum.ThirdValue) { // Do something }
回答
比较枚举类型的变量时,不必强制转换为int:
public void DoStuff<T>(T value);
我相当喜欢函数的隐式泛型参数。例如,如果我们有:
DoStuff<int>(5);
而不是像这样调用它:
DoStuff(5);
你可以:
- 如果通过反射调用该方法,则此方法不起作用。
- 我记得在Mono上遇到了一些奇怪的问题。
回答
它将根据参数的类型得出通用类型。
if( myString.ToUpper() == theirString.ToUpper() ){ ... }
许多人没有意识到他们可以使用以下方法比较字符串:OrdinalIgnoreCase而不是必须执行someString.ToUpper()。这消除了额外的字符串分配开销。
if( myString.Equals( theirString, StringComparison.OrdinalIgnoreCase ) ){ ... }
回答
变成
我最喜欢的属性:InternalsVisibleTo
在程序集级别,我们可以声明另一个程序集可以看到内部。出于测试目的,这绝对是很棒的。
[assembly: InternalsVisibleTo("MyLibrary.Test, PublicKey=0024...5c042cb")]
将其粘贴在AssemblyInfo.cs或者等效文件中,测试程序集即可完全访问所有需要测试的内部内容。
如我们所见,测试程序集必须具有强名才能获得被测试程序集的信任。
回答
FIXED / Power of Pointers in C# - This topic is too big, but I will just outline simple things.
在.Net Framework 2.0 +,Compact Framework 2.0+和XNA Framework 1.0+中可用。
struct cType{ char type[4]; int size; char name[50]; char email[100]; } cType myType; fread(file, &mType, sizeof(mType));
在C语言中,我们具有加载结构的便利,例如...
[Layout(LayoutKind.Sequential, Pack=1)] public unsafe class CType{ public fixed byte type[4]; public int size; public fixed byte name[50]; public fixed byte email[100]; }
我们可以在"不安全"方法中使用fixed关键字来读取字节数组对齐的结构。
CType mType = new CType(); byte[] buffer = new byte[Marshal.SizeOf(CType)]; stream.Read(buffer,0,buffer.Length); // you can map your buffer back to your struct... fixed(CType* sp = &mType) { byte* bsp = (byte*) sp; fixed(byte* bp = &buffer) { for(int i=0;i<buffer.Length;i++) { (*bsp) = (*bp); bsp++;bp++; } } }
方法1(从常规流中读取到字节缓冲区,并将字节数组映射到结构的各个字节)
CType mType = new CType(); fixed(CType* p = &mType) { User32.ReadFile(fileHandle, (byte*) p, Marshal.SizeOf(mType),0); }
回答
方法2,我们可以将Win32 User32.dll的ReadFile映射为直接读取字节...
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; } }
通用代码中default关键字的用法,用于返回类型的默认值。
回答
这里的另一个例子
回答
InternalsVisibleToAttribute指定通常仅在当前程序集中可见的类型对另一个程序集可见。关于msdn的文章
Console.WriteLine("{0} item(s) found.", count);
而不是像这样俗气地做一些事情:
Console.WriteLine("{0} item{1} found.", count, count==1 ? "" : "s");
我使用以下内联技巧:
回答
当有一个项目时,将显示"项目";在有多个项目(或者少于)时,将显示"项目"。
很多人不知道的一件事是一些C#引入的预处理程序指令。我们可以使用#error这是一个错误。来生成编译器错误,而#warning这是一个警告。
回答
在使用自上而下的方法作为"待办事项"列表进行开发时,通常会使用它们。我将以" #error实现此功能"或者" #warning最终实现此极端情况"作为提醒。
在处理C ++和C#之间的互操作时,许多人没有意识到C ++ / CLI是一个不错的选择。
假设我们有一个C ++ DLL和一个依赖于C ++ DLL的CDLL。通常,最简单的技术是使用/ clr开关编译C ++ DLL的某些(或者全部)模块。要进行Ccall,C ++ DLL是在C ++ DLL中编写托管的C ++包装器类。 C ++ / CLI类可以比C#无缝得多地调用本机C ++代码,因为C ++编译器将自动为我们生成P /调用,具有专门用于互操作的库,以及用于互操作的语言功能(例如pin_ptr)。并且它允许托管代码和本机代码在同一二进制文件中共存。
回答
在Cside上,我们只需像其他任何.NET二进制文件一样调用DLL。
AmbientValueAttribute
我对这个问题太迟了,但是我想补充一些我认为没有涉及的问题。这些不是特定于C#的,但是我认为对于任何Cdeveloper来说都是值得一提的。
隔离存储设置
这类似于" DefaultValueAttribute",但是它没有提供属性默认的值,而是提供了属性用来决定是否从其他地方请求其值的值。例如,对于WinForms中的许多控件,它们的ForeColor
和BackColor
属性的AmbientValue
为Color.Empty
,以便他们知道从其父控件获取颜色。
标记与扩展方法的交互
这是Silverlight之一。该框架方便地包含此密封类,用于在每个应用程序和每个站点级别提供设置持久性。
public static bool Contains( this MyEnumType enumValue, MyEnumType flagValue) { return ((enumValue & flagValue) == flagValue); } public static bool ContainsAny( this MyEnumType enumValue, MyEnumType flagValue) { return ((enumValue & flagValue) > 0); }
使用扩展方法,标志枚举的使用更具可读性。
回答
这使得对标志值的检查变得很好并且易于读取和写入。当然,如果可以使用泛型并将T强制为枚举会更好,但这是不允许的。也许"动态"将使此过程变得容易。
void FileMessageEvent(object sender, MessageEventArgs e) { if (this.InvokeRequired == true) { this.BeginInvoke((MethodInvoker)delegate { lblMessage.Text=e.Message; Application.DoEvents(); } ); } }
当我们要调用/ BeginInvoke内联代码时,内置的(2.0)MethodInvoker委托非常有用。这样可以避免创建实际的委托和单独的方法。
回答
解决了错误:"因为它不是委托类型,所以无法将匿名方法转换为类型'System.Delegate'"。
string output = "helo world!"; Action action = () => Console.WriteLine(output); output = "hello!"; action();
我发现令人难以置信的是,编译器遇到什么类型的麻烦才能使用外部变量来编写代码:
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();
实际上打印出" hello!"。为什么?因为编译器会为委托创建一个嵌套类,并为所有外部变量提供公共字段,并在每次对委托的每次调用之前插入设置代码:)这是上面的代码" reflectored":
回答
我觉得很酷。
int[] someArrayYouHaveAsInt; double[] copyOfArrayAsDouble = Array.ConvertAll<int, double>( someArrayYouHaveAsInt, new Converter<int,double>(Convert.ToDouble));
我无法弄清楚Convert
类中的某些功能有什么用途(例如Convert.ToDouble(int),Convert.ToInt(double)),直到将它们与Array.ConvertAll`结合使用为止:
int[] someArrayYouHaveAsInt; double[] copyOfArrayAsDouble = Array.ConvertAll<int, double>( someArrayYouHaveAsInt, new Converter<int,double>( delegate(int i) { return (double)i; } ));
回答
这避免了由于定义内联委托/关闭(且可读性更高)而引起的资源分配问题:
var pets = new[] { "Cat", "Dog", "Bird" };
回答
不指定数组元素类型的数组初始化:
static void Example() { int i = 0; top: Console.WriteLine(i.ToString()); if (i == 0) { i++; goto top; } }
回答
好吧...不要使用它,但是很多人都不知道Csupports支持邪恶的goto :)
刚刚学习了不变性,协方差和逆变的含义之后,我发现了.NET 4.0中将包含的in和out通用修饰符。它们似乎晦涩难懂,以至于大多数程序员都不知道它们。
回答
Visual Studio Magazine上有一篇文章讨论了这些关键字以及如何使用它们。
狂暴目标
[assembly: ComVisible(false)]
每个人都看过一个。基本上,当我们看到以下内容时:
[return: SomeAttr] int Method3() { return 0; }
该属性的"程序集:"部分是目标。在这种情况下,该属性将应用于装配,但还有其他一些:
回答
在此示例中,将属性应用于返回值。
回答
如果要防止垃圾收集器运行对象的终结器,只需使用GC.SuppressFinalize(object);
。同样,GC.KeepAlive(object);
将防止垃圾收集器通过引用该对象来收集该对象。至少在我的经验中不是很常用,但是很高兴知道以防万一。
private double _Zoom = 1; [Category("View")] [Description("The Current Zoom Level")] public double Zoom { get { return _Zoom;} set { _Zoom = value;} }
在设计视图中查看零部件时要显示的属性:
回答
使组件库的其他用户更轻松地进行操作。
回答
仔细使用后,反射力将非常强大。我在电子邮件模板系统中使用了它。模板管理器将被传递一个对象,而html模板将具有引用属性的嵌入字段,可以使用反射从传递的对象中检索该属性。工作得很好。
... 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)); ... }
在.NET 3.5中与lambda语句一起使用时,一定是Func <>类型。这些允许自定义的功能,并且在提供用户可自定义的对象而无需将其子类化或者诉诸某种有限的系统(例如跟踪列出用户想要监视的按钮或者键的变量)方面提供了很大帮助。同样,它们可以像常规方法一样被调用,并且可以像变量一样被赋值。我唯一想到的缺点是我们只能使用5个参数!尽管到那时我们可能想要考虑其他解决方案...
编辑:提供一些示例。
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函数用于快速事件引发程序的示例,而无需麻烦代表。
编辑:想到了另一个。空值! Chas最接近可选参数。
[Flags] public enum ConfigOptions { None = 0, A = 1 << 0, B = 1 << 1, Both = A | B } Console.WriteLine( ConfigOptions.A.ToString() ); Console.WriteLine( ConfigOptions.Both.ToString() ); // Will print: // A // A, B
回答
FlagsAttribute,使用枚举制作位掩码时的一个小巧但不错的功能:
回答
如果我们在Visual Studio工具栏中有搜索文本框,则可以输入"> of Program.cs"以打开文件Program.cs
enum EnumName : [byte, char, int16, int32, int64, uint16, uint32, uint64] { A = 1, B = 2 }
回答
可以为枚举定义数据类型:
我中的一些人把他们变成了你想要的。
[assembly::InternalsVisibleTo("SomeAssembly")]
属性:
允许我们将内部方法/属性或者数据从程序集公开到另一个名为" SomeAssembly"的程序集。所有受保护/私有的内容都保持隐藏。
public MyClass { public static MyClass() { // type init goes here } ...... }
静态构造函数(也称为"类型构造函数")
回答
高级调试
展示
关键字"内部"。在许多方面都非常有用。
已经提到的属性DebuggerDisplay和DebuggerBrowsable控制元素的可见性和显示的文本值。简单地重写ToString()将使调试器使用该方法的输出。
罢工之子
如果需要更复杂的输出,可以使用/创建Debugger Visualizer,下面是几个示例
在这里可用。
用于框架源的Symbol Server
Microsoft提供了称为SOS的调试器扩展。这是一个非常强大的(尽管常常令人困惑)扩展,它是诊断"泄漏"(更准确地说是对不再需要的对象的不需要的引用)的一种极好的方法。
2010年的变化
遵循这些指示信息将使我们逐步了解框架某些部分的源代码。
- 调试并行任务
- 并行堆栈允许同时查看多个线程调用堆栈。
- 通过"历史记录调试",我们可以及时查看事件和非局部变量(只要我们预先启用了收集)。调试方式的潜在重大变化。
回答
Visual Studio 2010中存在一些增强功能和新功能:
使用"抛出;"而不是" throw ex;"保留堆栈跟踪
回答
如果在不添加其他信息的情况下重新抛出异常,请使用" throw"而不是" throw ex"。 catch块中的空" throw"语句将发出特定的IL,该IL将重新引发异常,同时保留原始堆栈跟踪。 " throw ex"将堆栈跟踪丢失到异常的原始源。
能够基于这样的通用参数创建类型的实例
回答
新的T();
当Yield关键字功能强大时,通常会被忽略。不久前,我在博客上对此进行了讨论,并讨论了收益(不同的处理方式),该收益发生在单产的背景下,有助于加深理解。
回答
在C#中使用Yield
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
参数,从扩展方法中创建委托,就好像它们是常规方法一样。例如,
回答
请注意,这不适用于扩展方法
值类型;看到这个问题。
[ThreadStatic] private static int _ThreadStaticInteger;
不确定是否提到了这一点,但是ThreadStatic属性是一个非常有用的东西。这使得仅针对当前线程的静态字段为静态。
我们不应该包含初始化程序,因为它只对整个应用程序执行一次,因此最好使该字段为可空状态,并在使用该值之前检查该值是否为null。
ASP.NET应用程序线程还有另外一件事可以重用,因此,如果我们修改该值,则最终可能会被用于另一个页面请求。
using (DbTransaction tran = new DbTransaction()) { DoQuery("..."); DoQuery("..."); }
我仍然在一些场合发现了这一点。例如,在创建自定义交易类时:
DbTransaction构造函数将ThreadStatic字段设置为其自身,并在dispose方法中将其重置为null。 DoQuery检查静态字段,如果!= null,则使用当前事务;否则,默认为其他值。我们避免将事务传递给每个方法,另外,它还可以轻松地将非本来打算与事务一起使用的其他方法包装在事务内...
回答
HttpContext.Current.Server.Execute
只是一种用途:)
Page pageHolder = new Page(); UserControl viewControl = (UserControl)pageHolder.LoadControl(@"MyComponent.ascx"); pageHolder.Controls.Add(viewControl); StringWriter output = new StringWriter(); HttpContext.Current.Server.Execute(pageHolder, output, false); return output.ToString();
回答
对于将HTML呈现为AJAX回调的字符串非常有用。我们可以将其与组件一起使用,而不是将HTML字符串片段拼凑在一起。我能够将页面膨胀减少几百KB,几乎没有混乱。我这样使用它:
[field:NonSerializable] public event SomeDelegate SomeEvent;
回答
营销活动不可序列化:
我们可以通过较少的键入来添加和删除委托。
handler += new EventHandler(func);
通常的方式:
handler += func;
回答
减少打字方式:
//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 {...}
回答
通用约束:
x |= y
"或者"赋值运算符非常好。我们可以这样写:
x = x | y
代替这个:
回答
如果必须以" false"开头的变量或者属性(在示例中为" x"),但是仅当其他值是" boolean"时,才想将其更改为其他布尔型变量/属性的值,这通常很实用。是的。
扩展方法可以在null
上调用;这不会导致抛出" NullReferenceException"。
回答
示例应用程序:我们可以为ToString()定义一个名为ToStringOrEmpty()的替代方法,该替代方法在对null调用时将返回空字符串。
我已经通读了全部七个页面,但我错过了这些页面:
字符串连接
String.Join(",", new String[] { "a", "b", "c"});
我见过很多for循环,可将项目列表转换为带分隔符的字符串。确保我们不以分隔符开头并且不以分隔符结尾总是很痛苦的。内置方法使此操作更容易:
评论中的TODO
// TODO: Implement this! throw new NotImplementedException();
并不是真正的功能,更多的是Visual Studio功能。当我们使用TODO开始注释时,注释将添加到Visual Studio任务列表中("视图"->"任务列表"。注释)
扩展方法符合泛型
public static void Process<T>(this T item) where T:ITest,ITest2 {}
我们可以将扩展方法与泛型结合使用,当我们想到本主题前面的技巧时,可以将扩展添加到特定的接口
可枚举范围
Enumerable.Range(0, 15)
只需要一个整数列表?
回答
我会尝试考虑更多...
C#中的指针。
string str = "some string"; Console.WriteLine(str); unsafe { fixed(char *s = str) { char *c = s; while(*c != '// defines a descriptive name for a complexed data type using MyDomainClassList = System.Collections.Generic.List< MyProjectNameSpace.MyDomainClass>; .... MyDomainClassList myList = new MyDomainClassList(); /* instead of List<MyDomainClass> myList = new List<MyDomainClass>(); */') { *c = Char.ToUpper(*c++); } } } Console.WriteLine(str);
它们可用于执行就地字符串操作。这是一项不安全的功能,因此unsafe关键字用于标记不安全代码的区域。另请注意,fixed关键字是如何用于指示指向的内存是固定的,并且不能由GC移动。指针指向内存地址非常重要,GC可以将内存移动到其他地址,否则会导致指针无效。
回答
我永远不会这样做,只是为了这个问题来演示此功能。
using FloatValue = float; // you only need to change it once to decimal, double... .... FloatValue val1; ...
我喜欢使用using指令重命名某些类,以便于阅读,例如:
Func<int,int> f = x => x + 1;
回答
这对于代码维护也非常方便。如果我们需要更改类名,则只需更改一个地方。另一个例子:
回答
异常过滤器。因此,"隐藏"我们甚至在没有后编译补丁的情况下也无法使用它们(至少从C#中使用);)
表达式树怎么样?它们是LINQ的核心,并允许延迟执行:
摘自David Hayden的博客:
var three = f(2); // 2 + 1
在C3.0中,可以使用lambda表达式如下定义委托:
Expression<Func<int,int>> expression = x => x + 1;
该委托被编译为应用程序中的可执行代码,可以这样调用:
该代码可以按预期工作。这里没什么好看的。
表达树
var originalDelegate = expression.Compile(); var three = originalDelegate.Invoke(2);
通过使用System.Query.Expression将委托定义为表达式树时:
该委托不再被编译为可执行代码,而是被编译为可以转换并编译为原始委托的数据。
[field: NonSerialized] public event EventHandler Event;
回答
DateTime? myDate = null; if (myDate.HasValue) { //doSomething } else { //soSomethingElse }
为了在应用程序中实际使用表示为表达式树的委托,我们必须在应用程序中对其进行编译和调用:
这样,事件侦听器不会被序列化。
回答
只是[NonSerialized]不起作用,因为NonSerializedAttribute仅可应用于字段。
string[] itemList = { "Example 1", "Example 2", "Example 3" }; CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection(); commaStr.AddRange(itemList); //outputs Example 1,Example 2,Example 3
回答
我特别喜欢可为空的DateTime。因此,如果我们有某些情况下给出了日期,而另一些情况下没有给出日期,我认为这是最好的用法,恕我直言,因为使用DateTime.MinValue
或者其他方法更容易理解...
()=>Console.ReadLine()
如果我们试图从项目列表中创建一个逗号分隔的字符串,请执行以下操作:
回答
在这里查看另一个示例。
for (;;);
回答
零参数Lambdas
while (true) ;
我没看到这个:
public static class Strings { public static bool IsNullOrEmpty(this string value) { return string.IsNullOrEmpty(value); } }
回答
与...相同
var input = Console.ReadLine(); if (input.IsNullOrEmpty()) { Console.WriteLine("try again"); }
我正在成为扩展方法的忠实拥护者,因为它们可以在现有代码或者我们无法编辑的代码中添加更多有用的功能。我现在添加到我所做的所有操作中的最爱之一是string.IsNullOrEmpty()
string s = string.Format("{0:positive;negative;zero}", i);
回答
这使我们可以像这样缩短代码
条件字符串。格式:
string format = "000;-#;(0)"; string pos = 1.ToString(format); // 001 string neg = (-1).ToString(format); // -1 string zer = 0.ToString(format); // (0)
根据数字是正数,负数还是零,对数字应用不同的格式。
Objects that implement this interface can receive notification that an event has occurred, and they can respond to queries about the event. In this way, clients can ensure that one request has been processed before they submit a subsequent request that depends on completion of the first.
回答
例如
在标准中已经对此进行了很多解释。对于任何初学者和专家来说,这都是一本好书,它读起来很多,但它是官方标准,并且充满了多汁的细节。
一旦我们完全理解了C#,就该进一步了解公共语言基础结构的基础了。 C#的体系结构和基础。
我遇到过各种各样的程序员,除了程序员的坚持的限制外,他们不知道对象和ValueType之间的区别。
回答
熟悉这两个文档,我们将永远不会成为那个人。
当我们需要(a)在对象之间就事件的发生进行同步通信时,有一个专用接口ISynchronizeInvoke。
protected void OnEvent<T>(EventHandler<T> eventHandler, T args) where T : EventArgs { if (eventHandler == null) return; foreach (EventHandler<T> singleEvent in eventHandler.GetInvocationList()) { if (singleEvent.Target != null && singleEvent.Target is ISynchronizeInvoke) { var target = (ISynchronizeInvoke)singleEvent.Target; if (target.InvokeRequired) { target.BeginInvoke(singleEvent, new object[] { this, args }); continue; } } singleEvent(this, args); } }
引用MSDN文章(链接):
public event EventHandler<ProgressEventArgs> ProgressChanged; private void OnProgressChanged(int processed, int total) { OnEvent(ProgressChanged, new ProgressEventArgs(processed, total)); }
这是一个通用包装器:
DateTime? date = null;
回答
这是一个示例用法:
在C3.5中初始化字典的表达式:
回答
new Dictionary <string,Int64>(){{" Testing",123},{" Test",125}};
我认为没有人提到添加内容吗?值类型名称之后将使其可为空。
class Base { } class Foo: Base { } class Bar: Base { }
你可以做:
回答
DateTime是一个结构。
从C / C ++迁移的程序员可能会错过以下内容:
回答
在C#中,%(取模运算符)在浮点数上起作用!
泛型和"好奇地重复出现的模板模式"确实对某些静态方法/属性声明有所帮助。
class Base { public static Base Get() { // Return a suitable Base. } } class Foo: Base { public static Foo Get() { // Return a suitable Foo. } } class Bar: Base { public static Bar Get() { // Return a suitable Bar. } }
假设我们正在构建一个类层次结构:
class Base<T> where T: Base<T> { public static T Get<T>() { // Return a suitable T. } }
现在,我们想在类型上声明静态方法,这些方法应采用相同类型的参数(或者返回值)或者相同类型的静态属性。例如,我们想要:
class Foo: Base<Foo> { } class Bar: Base<Bar> { }
如果这些静态方法基本上都做相同的事情,那么我们手上就会有很多重复的代码。一种解决方案是在返回值上放下类型安全性,并始终返回" Base"类型。但是,如果我们需要类型安全性,那么解决方案是将" Base"声明为:
public class Singleton<T> where T: Singleton<T>, new() { public static T Instance { get; private set; } static Singleton<T>() { Instance = new T(); } }
而" Foo"和" Bar"为:
这样,他们将自动获得静态方法的副本。
[System.ComponentModel.Browsable(false)] public String LastActionID{get; private set;}
这也可以将单例模式封装在基类中(我知道下面的代码不是线程安全的,只是为了说明一点),这很可行:
回答
我意识到这迫使我们在单例子类上有一个公共的无参数构造函数,但是如果没有where T:protected new()
;的构造方法,则无法避免这种情况。但是,可以使用反射在运行时调用子类的受保护/私有无参数构造函数来实现这一点。
回答
埃里克·利珀特(Eric Lippert)的《四个开关怪异》
[System.ComponentModel.DisplayName("Last Action")] public String LastAction{get; private set;}
防止DataGridView显示属性:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] private DataController p_dataSources;
使我们可以为组件(如DataGrid或者DataGridView)设置友好的显示:
decimal? MyValue = null;
回答
对于后备变量,如果我们不希望直接访问它们,那么将变得更加困难:
回答
使用LINQ对用于进行迭代和条件处理的集合进行内联工作的能力非常有价值。值得学习所有LINQ扩展方法如何帮助使代码更加紧凑和可维护。
我最近刚学到的一个方法是,我们仍然可以在可为空的值上调用方法...。
MyValue == null ? null : MyValue .ToString()
事实证明,当我们具有可为空的值时会怎样:
MyValue.ToString()
我们可能认为必须写的地方:
namespace ns { class Class1 { Nullable<int> a; } }
我们可以改写:
回答
我知道我可以调用MyValue.HasValue和MyValue.Value ...,但是并没有完全单击,我可以调用ToString()。
namespace ns { class Class1 { int? a; } }
这将无法编译:
找不到类型或者名称空间名称" Nullable"(我们是否缺少using指令或者程序集引用?)<-缺少" using System;"
public class Outer { private int Value { get; set; } public class Inner { protected void ModifyOuterMember(Outer outer, int value) { outer.Value = value; } } }
但
回答
会编译! (.NET 2.0)。
public class Cheater : Outer.Inner { protected void MakeValue5(Outer outer) { ModifyOuterMember(outer, 5); } }
嵌套类可以访问外部类的私有成员。
var s = new Func<String>(() => { return "Hello World!"; })();
现在,与上述功能一起,我们还可以从嵌套类继承,就好像它们是顶级类一样,如下所示。
回答
这些功能为通过某些隐藏的类提供对特定成员的访问提供了一些有趣的可能性。
类似于JavaScript的匿名内联函数
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) + "…" : s;
替代语法
[DebuggerTypeProxy(typeof(HashtableDebugView))] class MyHashtable : Hashtable { private const string TestString = "This should not appear in the debug window."; internal class HashtableDebugView { private Hashtable hashtable; public const string TestStringProxy = "This should appear in the debug window."; // The constructor for the type proxy class must have a // constructor that takes the target type as a parameter. public HashtableDebugView(Hashtable hashtable) { this.hashtable = hashtable; } } }
回答
缩短字符串并添加水平省略号...
@
首先是DebuggerTypeProxy。
在第二个:
回答
ICustomTypeDescriptor
如果有人提到此问题,我深表歉意,但我经常使用它。
Alex Papadimoulis开发了Visual Studio的外接程序。它用于将常规文本粘贴为字符串,字符串生成器,注释或者区域。
http://weblogs.asp.net/alex_papadimoulis/archive/2004/05/25/Smart-Paster-1.1-Add-In---StringBuilder-and-Better-C_2300_-Handling.aspx
string s = "A line of text" + Environment.NewLine + "Another with a \"quote\"!!";
在这个插件中(我也不知道是否已经提到过),我注意到字符串是使用字符串文字前缀粘贴的:
我知道这些,但是我不知道在文字中使用双引号来转义引号。
string s = @"A line of text Another with a ""quote""!!";
例如
[AttributeUsage(AttributeTargets.All)] public class X: Attribute {} [AttributeUsage(AttributeTargets.All)] public class XAttribute: Attribute {} [X] // Error: ambiguity class Class1 {} [XAttribute] // Refers to XAttribute class Class2 {} [@X] // Refers to X class Class3 {} [@XAttribute] // Refers to XAttribute class Class4 {}
回答
可以表示为
定义自定义属性时,可以将其与[MyAttAttribute]或者[MyAtt]一起使用。
当两个著作都存在类时,就会发生编译错误。
using (Font f1= new Font("Arial", 10.0f), f2 = new Font("Arial", 10.0f)) { // Use f1 and f2. }
回答
@特殊字符可用于区分它们:
using (Font f1= new Font("Arial", 10.0f)) using (Font f2 = new Font("Arial", 10.0f)) { }
我们可以在一个using语句中"使用"多个对象。
a hidden feature is a wasted feature
请注意,已经有一个答案说明我们可以执行以下操作:
回答
与我的不同。
{ string test2 = "3"; Console.Write(test2); } Console.Write(test2); //compile error
不确定Microsoft是否会喜欢此问题,尤其是有这么多答复。
我确定我曾经听过Microsoft负责人说:
回答
...或者类似的东西。
public delegate void MyCustomEventHandler(object sender, MyCustomEventArgs e); public class MyCustomEventClass { public event MyCustomEventHandler MyCustomEvent; }
我们可以使用" {}"括号来限制变量的寿命,从而限制变量的范围。
回答
test2仅存在于方括号内。
很抱歉发布这么晚,我是Stack Overflow的新手,所以错过了早期的机会。
我发现EventHandler <T>是未充分利用的框架的重要功能。
我遇到的大多数Cdeveloper在定义自定义事件时仍会定义一个自定义事件处理程序委托,这不再需要了。
public class MyCustomEventClass { public event EventHandler<MyCustomEventArgs> MyCustomEvent; }
代替:
container.RegisterType(typeof(IRepository<>), typeof(NHibernateRepository<>));
你可以走了:
回答
这更加简洁,而且我们不必陷入将委托放置在包含事件的类的Eventcs或者.EventArgs派生类的.cs文件中的难题。
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 } }
回答
开放泛型是另一个方便的功能,尤其是在使用控制反转时:
在包含转义字符的字符串之前使用@。
基本上,当使用物理路径分配字符串变量时,每个人都在字符串中使用转义符的情况下使用" "。
例如
字符串strPath =" D:\ websites \ web1 \ images ";
但是转义字符可以在字符串值之前使用@忽略。
回答
例如
字符串strPath = @" D:\ websites \ web1 \ images ";
我喜欢滥用静态模板类不共享其静态成员的事实。
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); } ); }
这是一个线程安全的(在创建时),并且在编译时已知Type实例时,它可以廉价地替代任何Dictionary <Type,...>。
回答
干杯,
弗洛里安
public interface IReadOnlyFoo { object SomeReadOnlyProperty { get; } }
下面的一个不是隐藏的,但是相当隐含。我不知道是否在这里发布了以下示例的样本,并且我看不出有什么好处(可能没有好处),但是我将尝试显示一个"怪异"的代码。下面的示例通过C(代理/匿名委托[lambdas])和闭包中的函子模拟for
语句。其他流程语句,例如,if,if / else,while和do / whle也可以模拟,但是我不确定是否使用switch(也许我太懒了:)。我对示例源代码进行了一些压缩,以使其更加清晰。
回答
如果我没看错,那么这种方法相对于函数式编程实践来说是相当不错的。我对吗?
internal class Foo : IReadOnlyFoo { public object SomeReadOnlyProperty { get; internal set; } }
即使接口声明本身没有属性设置器,也可以使我们将属性设置器方法添加到实现只读接口属性的具体类型中。例如:
// Create a Foo instance Foo foo = new Foo(); // This statement is legal foo.SomeReadOnlyProperty = 12345; // Make Foo read only IReadOnlyFoo readOnlyFoo = foo; // This statement won't compile readOnlyFoo.SomeReadOnlyProperty = 54321;
具体的类如下所示:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { //if (e.CommandName == "sel") //{ // lblCat.Text = e.CommandArgument.ToString(); //} }
回答
有趣的是,如果将Foo类强制转换为IReadOnlyFoo接口,则它是不可变的:
e.CommandName == "sel" lblCat.Text = e.Comman
我只想复制没有注释的代码。因此,诀窍是只需按下Alt按钮,然后突出显示我们喜欢的矩形(例如下面的矩形)。
#if DEBUG if (Debugger.IsAttached) Debugger.Break(); #endif
在上面的代码中,如果我想选择:
然后按ALt键并选择矩形,无需取消注释线。
回答
看一下这个。
Thread.MemoryBarrier
:大多数人不会使用它,并且MSDN上有一些不正确的信息。但是,如果我们知道复杂性,那么可以进行漂亮的无锁同步。volatile,Thread.VolatileRead,Thread.VolatileWrite
:很少有人会使用这些,而了解他们要避免并引入的所有风险的人就更少了。ThreadStatic
变量:在过去的几年中,只有一种情况我发现ThreadStatic变量绝对是上帝不可或者缺的,并且是必不可少的。例如,当我们想为整个呼叫链做某事时,它们非常有用。- 固定关键字:当我们想要访问大型数组的元素几乎与C ++一样快时,这是一种隐藏的武器(默认情况下,C#强制执行绑定检查,这会使事情变慢)。
- default(typeName)关键字也可以在泛型类之外使用。创建空的struct副本很有用。
- 我使用的方便功能之一是
DataRow [columnName] .ToString()
总是返回非null值。如果数据库中的值为NULL,则会得到空字符串。 - 当我们希望开发人员关注时,即使他/她尚未启用异常自动中断功能,也可以使用Debugger对象自动中断:
using ComplicatedDictionary = Dictionary<int, Dictionary<string, object>>; ComplicatedDictionary myDictionary = new ComplicatedDictionary();
- 我们可以为外观复杂的丑陋的通用类型添加别名,这样我们就不必一次又一次地复制粘贴。我们也可以在一处更改该类型。例如,
public IEnumerable<T> GetEnumerator(){ yield break; }
回答
C + CLR:
public class Tuple<V1, V2> : Tuple { public readonly V1 v1; public readonly V2 v2; public Tuple(V1 v1, V2 v2) { this.v1 = v1; this.v2 = v2; } }
回答
需要返回一个空的IEnumerable吗?
我不知道它是否已经发布(我扫描了第一篇文章,找不到它)。
Tuple<int, string> tup = new Tuple<int, string>(1, "Hello, World!");
最好用一个示例来说明,假设我们有这个类(模拟一个元组),以试图演示使之成为可能的所有语言功能,我将逐步进行介绍。
var tup = new Tuple<int, string>(1, "Hello, World!");
每个人都知道如何创建它的实例,例如:
public static void Create<T1, T2>() { // stuff }
不完全是火箭科学,现在我们当然可以将变量的类型声明更改为var,如下所示:
Create<float, double>();
仍然众所周知,这是一个带有类型参数的静态方法,每个人都应该熟悉它:
public static void Create<T1, T2>(T1 a, T2 b) { // stuff }
再次称呼它是这样的:
Create<float, string>(1.0f, "test"); Create(1.0f, "test");
大多数人不知道的是,如果泛型方法的参数包含所有其需要的类型,则可以推断出它们的类型,例如:
public abstract class Tuple { public static Tuple<V1, V2> Create<V1, V2>(V1 v1, V2 v2) { return new Tuple<V1, V2>(v1, v2); } }
这两个调用是相同的:
var tup = Tuple.Create(1, "Hello, World!");
由于T1和T2是根据我们传递的参数推断出来的。将此知识与var关键字结合,我们可以通过添加第二个静态类和一个静态方法,例如:
public abstract class Tuple { public static Tuple<V1, V2> Create<V1, V2>(V1 v1, V2 v2) { return new Tuple<V1, V2>(v1, v2); } } public class Tuple<V1, V2> : Tuple { public readonly V1 v1; public readonly V2 v2; public Tuple(V1 v1, V2 v2) { this.v1 = v1; this.v2 = v2; } } // Example usage: var tup = Tuple.Create(1, "test");
实现此效果:
这意味着:变量" tup"的类型," Create"的类型参数和" Create"的返回值都是从我们作为参数传递给Create的类型中推断出来的
using System; using System.Collections.Generic; static class Program { public static Type GetDeclaredType<T>(T x) { return typeof(T); } // Demonstrate how GetDeclaredType works static void Main(string[] args) { IList<string> iList = new List<string>(); List<string> list = null; Console.WriteLine(GetDeclaredType(iList).Name); Console.WriteLine(GetDeclaredType(list).Name); } }
完整的代码如下所示:
回答
这使我们可以在任何地方使用完全类型推断的工厂方法!
我喜欢EditorBrowsableAttribute。它使我们可以控制在Intellisense中是否显示方法/属性。我们可以将值设置为"始终","高级"或者"从不"。
从MSDN ...
评论
EditorBrowsableAttribute是对设计者的提示,指示是否要显示属性或者方法。我们可以在视觉设计器或者文本编辑器中使用此类型来确定用户可见的内容。例如,Visual Studio中的IntelliSense引擎使用此属性来确定是显示属性还是方法。
回答
在Visual C#中,我们可以使用"工具" |"工具" |"隐藏高级成员"设置来控制何时在IntelliSense和"属性"窗口中显示高级属性。选项|文字编辑器| C#。相应的EditorBrowsableState为"高级"。
IList`1 List`1
轻松确定声明变量的类型(根据我的回答):
static void Main(string[] args) { Console.WriteLine("Name is '{0}'", GetName(new {args})); Console.ReadLine(); } static string GetName<T>(T item) where T : class { var properties = typeof(T).GetProperties(); return properties[0].Name; }
结果:
enum Country { UnitedKingdom, UnitedStates, UnitedArabEmirates, }
及其名称(从"获取变量名称"中借用):
回答
结果:名字是'args'
将枚举值转换为字符串值
public static void PrintEnumAsString( Country country ) { Console.Writeline( country.ToString() ); }
给定枚举
using System; using System.Collections; interface IFoo { void Foo(); } struct MyStructure : IFoo { public void Foo() { } } public static class Program { static void MethodDoesNotBoxArguments<T>(T t) where T : IFoo { t.Foo(); } static void Main(string[] args) { MyStructure s = new MyStructure(); MethodThatDoesNotBoxArguments(s); } }
使用它:
回答
将枚举值的名称打印为字符串,例如"英国"
我发现只有很少的开发人员知道此功能。
如果我们需要一个通过某个接口与值类型变量一起使用的方法(由此值类型实现),则很容易避免在方法调用期间装箱。
.method private hidebysig static void MethodDoesNotBoxArguments<(IFoo) T>(!!T t) cil managed { // Code size 14 (0xe) .maxstack 8 IL_0000: ldarga.s t IL_0002: constrained. !!T IL_0008: callvirt instance void IFoo::Foo() IL_000d: ret } // end of method Program::MethodDoesNotBoxArguments .method private hidebysig static void Main(string[] args) cil managed { .entrypoint // Code size 15 (0xf) .maxstack 1 .locals init ([0] valuetype MyStructure s) IL_0000: ldloca.s s IL_0002: initobj MyStructure IL_0008: ldloc.0 IL_0009: call void Program::MethodDoesNotBoxArguments<valuetype MyStructure>(!!0) IL_000e: ret } // end of method Program::Main
示例代码:
[field: NonSerialized()] public EventHandler event SomeEvent;
IL代码不包含任何框内说明:
请参见Richter,J. CLR via C#,第二版,第14章:接口,有关泛型和接口约束的部分。
回答
另请参阅我对另一个问题的回答。
public event EventHandler SomeEvent { add { // ... } remove { // ... } }
我能想到的几个:
这样可以防止事件被序列化。 "字段:"表示该属性应应用于事件的后备字段。
[DllImport("msvcrt40.dll")] public static extern int printf(string format, __arglist); static void Main(string[] args) { printf("Hello %s!\n", __arglist("Bart")); }
回答
另一个鲜为人知的功能是重写添加/删除事件处理程序:
var dict = new Dictionary<int, string> { { 10, "Hello" }, { 20, "World" } };
回答
__arglist以及
private static T CachePattern<T>(string key, Func<T> create) where T : class { if (cache[key] == null) { cache.Add(key, create()); } return cache[key] as T; }
回答
在需要对某些数据进行硬编码的快速黑客攻击和单元测试中,字典初始化程序总是很有用的。
public static IUser CurrentUser { get { return CachePattern<IUser>("CurrentUserKey", () => repository.NewUpUser()); } }
Action和Func委托助手与lambda方法一起使用。我将它们用于需要委托以提高可读性的简单模式。例如,一种简单的缓存模式将是检查所请求的对象是否在缓存中。如果存在,则:返回缓存的对象。如果不存在,则生成一个新实例,缓存该新实例并返回新实例。而是为每个对象编写1000次此代码,我可以从缓存中存储/检索,我可以编写一个简单的模式方法,如下所示:
//TODO: [something]
...那么我可以在自定义缓存管理器中使用以下代码,从而大大简化我的缓存获取/设置代码
回答
现在,只需编写一次简单的"日常"代码模式,就可以更轻松地重复使用恕我直言。我不必编写委托类型,也不必弄清楚如何实现回调等。如果我可以在10秒内编写它,那么我就不那么容易了。无论是惰性初始化还是上面显示的一些其他示例,都可以使用剪切/粘贴简单的代码模式...
private static void printNumbers(int [] intNumbers) { foreach(int element in intNumbers) { Console.WriteLine(element); } } private static void printNumbers(double[] doubleNumbers) { foreach (double element in doubleNumbers) { Console.WriteLine(element); } }
" TODO"属性和任务列表
回答
将其添加到代码中(间距很重要)会在任务列表中抛出一个项目,双击该项目会将我们跳转到代码中的适当位置。
private static void printNumbers<E>(E [] Numbers) { foreach (E element in Numbers) { Console.WriteLine(element); } }
我不知道通用方法可以避免使用方法重载。
下面是打印int和double数的重载方法。
[MessageId] INT, [MessageText] NVARCHAR(MAX) [MessageDate] DATETIME
回答
- 附上吗?类型以使其可为空,例如:int?
- " c:\ dir"而不是@" C:\ dir"
回答
通用方法,可以为上述两种方法提供一种方法
使用LINQ更加容易/简化ORM映射
struct Message { Int32 Id; String Text; DateTime Date; }
考虑此表:
List<Message> messages = new List<Message>(); foreach (row in DataTable.Rows) { var message = new Message { Id = Convert.ToInt32(row["MessageId"]), Text = Convert.ToString(row["MessageText"]), Date = Convert.ToDateTime(row["MessageDate"]) }; messages.Add(message); }
...这个结构:
var messages = DataTable.AsEnumerable().Select(r => new Message { Id = Convert.ToInt32(r["MessageId"]), Text = Convert.ToString(r["MessageText"]), Date = Convert.ToDateTime(r["MessageDate"]) }).ToList();
而不是按照以下方式进行操作:
var sb = new StringBuilder(); var count = list.Count(); for(int i = 0; i < count; i++) { if (sb.Length > 0) sb.Append(seperator); sb.Append(list[i]); } return sb.ToString();
在我看来,我们可以使用LINQ并用更少的代码行来完成相同的事情。更多风格。像这样:
回答
就像循环一样,这种方法可以嵌套。
阅读了所有这9页的内容后,我觉得我不得不指出一个未知的功能。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
- 下载ICSharpCode.ZipLib
- 或者,将Java库引用到项目中,并使用Java的内置库来利用GZip的压缩/解压缩方法。
对于.NET 1.1,这是正确的,对压缩文件使用压缩/解压缩,其中之一必须:
回答
我不知道是未充分利用的(即使在.NET 2 / 3.5的情况下,仍然使用ICSharpCode.ZipLib仍是),因为它已被合并到System.IO.Compression命名空间中的向上的标准BCL版本2中。请参见MSDN页面" GZipStream类"。
回答
我发现在Visual Studio中使用条件中断功能非常有用。我喜欢它允许我将值设置为某些值的方式,例如,只有在极少数情况下才能满足,然后我可以从那里进一步检查代码。
不知道这本身是否是秘密,但我喜欢System.Linq中添加的Enumerable(添加到IEnumerable)类。
http://msdn.microsoft.com/zh-CN/library/system.linq.enumerable_members.aspx
虽然yield关键字已经列出。迭代器块令人惊讶。我用它们来构建列表,将对其进行测试以查看它们是否是互质的。从根本上讲,它使我们可以遍历一个返回值并随时停止的函数。
噢,当我们无法再对其进行优化时,我几乎忘记了世界上最好的一类。 BackgroundWorker !!!
回答
http://msdn.microsoft.com/zh-CN/library/system.componentmodel.backgroundworker.aspx
return string.Join(separator, list.ToArray());
我没有找到任何使用string.Join的人使用分隔符来连接字符串。每个人都在写同样丑陋的for循环
public IEnumerable<Request> SomeMethod(IEnumerable<Request> requests) { foreach (Request request in requests) yield return DoSomthing(request); }
回答
代替
where T : Enum
回答
通过yield获得IEnumerable而无需显式创建IEnumerable对象的另一种方法
MailMessage mail = new MailMessage { To = { new MailAddress("[email protected]"), new MailAddress("[email protected]") }, Subject = "Password Recovery" };
我只想提及(由于OP运算,其中T:struct)Ccompiler的陷阱之一是
回答
将不会编译。它将引发错误"约束不能是特殊类'System.Enum'"。
public class User { public long UserId { get; set; } public String Name { get; set; } public String Password { get; set; } public String Email { get; set; } }
对象初始化程序中的集合初始化程序:
回答
我们可以在单个表达式中初始化整个树。
User user = new User(); user.UserId = 1; user.Name = "myname"; etc
我在这次对话中有点晚了,我想贡献以下内容。对于某些开发人员来说,这可能是新事物。
User user = new User() { UserId = 1, Name = "myname", Email = "[email protected]", Password = "mypassword" };
声明和初始化它的通常方法是使用构造函数或者类似的代码。
public enum MyEnumColors : uint { Normal = 0xFF9F9F9F, Active = 0xFF8EA98A, Error = 0xFFFF0000 }
回答
但是我学会了以下初始化方法。我知道Visual Basic开发人员会喜欢它,因为它就像仅在VB.NET中可用而在C中不可用的运算符一样,如下所示。
var subject = new Subject(); var doSomething = (Func<String, String>) Delegate.CreateDelegate(typeof(Func<String, String>), subject, "DoSomething"); Console.WriteLine(doSomething("Hello Freggles"));
回答
我们可以将颜色存储在Enum中。
IEnumerable<T>.Any();
使用Delegate.CreateDelegate调用私有方法的技巧非常巧妙。
回答
这是有用的上下文
回答
我不知道这是否是隐藏功能("")。任何字符串函数。
[DllImport ("gdi32.dll")] [return : MarshalAs(UnmanagedType.I4)] [StructLayout(LayoutKind.Sequential)]
- 但是IEnumerable
<T>
.Any()是最简洁的,性能也最好。
回答
要测试IEnumerable <T>在LINQ中是否为空,请使用:
大多数P / Invoke东西有点奇怪。
{ service.DoTonsOfWork(args); }
回答
属性示例:
带有括号的空块是允许的。
//using(var scope = new TransactionScope) { service.DoTonsOfWork(args); }
你可以这样写代码
[Flags] public enum Colors { None = 0, Red = 1, Blue = 2, White = 4, Black = 8, Green = 16, All = 31 //It seems pretty bad... }
回答
如果我们想尝试一些已经没有写过的"使用"或者"尝试...最终"的东西,这将很有帮助。
Visual Studio具有的最有用的功能之一是"制作对象ID"。它会生成一个id并将其"添加"到对象上,因此无论我们在哪里查看该对象,都将看到id(与线程无关)。
回答
调试时,右键单击变量工具提示,即可找到它。
它也适用于watched / autos / locals变量。
[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. }
对FlagAttribute和枚举使用"〜"运算符
有时我们会使用带有枚举的Flag属性对枚举执行按位操作。
public Func<int> RandomGenerator { get { var r = new Random(); return () => { return r.Next(); }; } } void SomeFunction() { var result1 = RandomGenerator(); var x = RandomGenerator; var result2 = x(); }
回答
请注意,枚举中选项" All"的值很奇怪。
取而代之的是,我们可以对带有标记的枚举使用"〜"运算符。
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 }
回答
1.更好的作用域行为
使用LINQ,可以基于参数创建新功能。
如果我们有一个经常执行的微小函数,那很好,但是参数需要一些时间才能计算出来。
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();
{在成员内部的任何地方},{仅使用花括号},{不带控制语句}。
2.用于代码美化或者视觉语义
在大型的,混乱的或者过时的成员内部(但是,它们不应该永远存在),可以帮助我防止使用错误的变量名。将内容范围扩大到更细的层次。
var somePerson = this.GetPerson(); // whatever { var p = somePerson; p.FirstName = "John"; p.LastName = "Doe"; //... p.City = "Gotham"; }
3.模仿" with"声明
例如,此XML编写代码遵循实际生成的XML的缩进级别(即Visual Studio将相应地缩进范围括号)
var value = -0.5; var value2 = 0.5; var value3 = 1.4; Console.WriteLine( Math.Round(value, MidpointRounding.AwayFromZero) ); //out: -1 Console.WriteLine(Math.Round(value2, MidpointRounding.AwayFromZero)); //out: 1 Console.WriteLine(Math.Round(value3, MidpointRounding.ToEven)); //out: 1
(还有将临时工作置于主要范围之外的另一种用途)
帕特里克(Patrik)提供:有时用于模仿C#中的VB"有声明"。
回答
对于挑剔的程序员。
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); } } }
然后,作为该类的成员,我们希望有一个"静态析构函数":
现在将在最终垃圾回收发生时调用此方法。如果我们绝对需要释放某些资源,这将很有用。
#if DEBUG //Code run in debugging mode #else //Code run in release mode #endif
一个快速且肮脏的程序表现出这种现象:
回答
程序退出时,将调用"静态析构函数"。
回答
Nullable.GetValueOrDefault吗?
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings(); xmlWriterSettings.NewLineOnAttributes = true; xmlWriterSettings.Indent = true; XmlWriter xml = XmlWriter.Create(@"C:\file.xml", xmlWriterSettings); // Start writing the data using xml.WriteStartElement(), xml.WriteElementString(...), xml.WriteEndElement() etc
回答
我喜欢
public class BoundObject : INotifyPropertyChanged { private int _value; private string _text; public event PropertyChangedEventHandler PropertyChanged; public int Value { get { return _value; } set { if (_value != value) { _value = value; OnPropertyChanged("Value"); } } } public string Text { get { return _text; } set { if (_text != value) { _text = value; OnPropertyChanged("Text"); } } } public void Init(){ _text = "InitialValue"; _value = 1; OnPropertyChanged(string.Empty); } public void Reset() { _text = "DefaultValue"; _value = 0; OnPropertyChanged(string.Empty); } private void OnPropertyChanged(string propertyName) { PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName); if (PropertyChanged != null) { PropertyChanged(this, e); } } }
参考带有永久链接的帖子" C#的隐藏功能?",还有另一种方法可以完成相同的缩进/换行符。看一下这个..
回答
我不确定这是否是未知功能!
IObservable呢?
几乎每个人都知道IEnumerable,但是他们的数学对偶似乎是未知的。也许是因为它是.NET 4中的新功能。
它所做的不是代替拉动信息(如枚举),而是将信息推送到可观察者的订户。
回答
与Rx扩展一起,它将改变我们处理事件的方式。只是为了说明它的强大功能,请在此处查看一个非常简短的示例。
当类实现INotifyPropertyChanged且要通知绑定系统(WPF,Silverlight等)对象(ViewModel)的多个绑定属性已更改时,可以使用null或者String.Empty引发PropertyChanged-Event。
class MyClass<T> where T : new() { }
回答
MSDN中对此进行了记录,但是代码示例和文章通常无法解释这种可能性。我发现它非常有用。
Dictionary<string, int> nameAgeDict = new Dictionary<string, int>(); nameAgeDict["Joe"] = 34; // no error. will just auto-add key/value nameAgeDict["Joe"] = 41; // no error. key/value just get overwritten nameAgeDict.Add("Joe", 30); // ERROR! key already exists
回答
这意味着T必须具有一个公共的无参数构造函数:
我正在阅读《 Pro ASP.NET MVC框架》(APress)一书,并观察到作者对我不熟悉的Dictionary对象正在做的事情。
public class StaticConstrucEx2Outer<T> { // Will hold a different value depending on the specicified generic type public T SomeProperty { get; set; } static StaticConstrucEx2Outer() { Console.WriteLine("StaticConstrucEx2Outer " + typeof(T).Name); } public class StaticConstrucEx2Inner<U, V> { static StaticConstrucEx2Inner() { Console.WriteLine("Outer <{0}> : Inner <{1}><{2}>", typeof(T).Name, typeof(U).Name, typeof(V).Name); } public static void FooBar() {} } public class SCInner { static SCInner() { Console.WriteLine("SCInner init <{0}>", typeof(T).Name); } public static void FooBar() {} } } StaticConstrucEx2Outer<int>.StaticConstrucEx2Inner<string, DateTime>.FooBar(); StaticConstrucEx2Outer<int>.SCInner.FooBar(); StaticConstrucEx2Outer<string>.StaticConstrucEx2Inner<string, DateTime>.FooBar(); StaticConstrucEx2Outer<string>.SCInner.FooBar(); StaticConstrucEx2Outer<string>.StaticConstrucEx2Inner<string, Int16>.FooBar(); StaticConstrucEx2Outer<string>.SCInner.FooBar(); StaticConstrucEx2Outer<string>.StaticConstrucEx2Inner<string, UInt32>.FooBar(); StaticConstrucEx2Outer<long>.StaticConstrucEx2Inner<string, UInt32>.FooBar();
他添加了一个新的键/值对,而没有使用Add()方法。然后,他改写了相同的键/值对,而不必检查该键是否已经存在。例如:
回答
在很多情况下,我不需要检查字典中是否已有键,而我只想添加相应的键/值对(如有必要,覆盖现有的键/值对。) ,在添加密钥之前,我始终必须检查密钥是否已经存在。
Outer <Int32> : Inner <String><DateTime> SCInner init <Int32> Outer <String> : Inner <String><DateTime> SCInner init <String> Outer <String> : Inner <String><Int16> Outer <String> : Inner <String><UInt32> Outer <Int64> : Inner <String><UInt32>
单独的静态字段取决于周围类的通用类型。
if ((x == y) || ((x != null && y != null) && x.Equals(y))) { ... }
回答
将产生以下输出
好的,这似乎很明显,但是我想提一下Object.Equals方法(静态方法,带有两个参数)。
if (Object.Equals(x, y)) { ... }
我敢肯定,很多人甚至都不了解它,或者忘记了它的存在,但是在某些情况下它确实可以提供帮助。例如,当我们想比较两个对象是否相等时,不知道它们是否为空。你写过多少次像这样的东西:
Console.WriteLine("Product: {0,-7} Price: {1,5}", product1, price1); Console.WriteLine("Product: {0,-7} Price: {1,5}", product2, price2);
当你可以写的时候:
回答
(实际上完全像第一个代码示例中那样实现了Object.Equals)
using ListOfDictionary = System.Collections.Generic.List<System.Collections.Generic.Dictionary<string, string>>;
string.Format()中的宽度
产生
回答
来自Prabir的博客|隐藏功能
回答
最近,我了解了String.Join方法。在构建诸如列之类的字符串以供查询选择时,它非常有用。
类型定义
ListOfDictionary list = new ListOfDictionary();
有人发贴说他们想念typedef,但是你可以这样
String.IsNullOrWhiteSpace(String value)
回答
并声明为
[Flags] public enum ErrorTypes { None = 0, MissingPassword = 1 << 0, MissingUsername = 1 << 1, PasswordIncorrect = 1 << 2 }
这是C4.0中字符串类的新方法:
回答
是时候了。
public static class EventExtensions { public static void Raise<T>(this EventHandler<T> @event, object sender, T args) where T : EventArgs { if(@event!= null) { @event(sender, args); } } }
回答
并不是真正的隐藏,但很有用。当我们有带有"标志"的"枚举"时,可以使用左移使内容更清晰。例如
public class MyImportantThing { public event EventHandler<MyImportantEventEventArgs> SomethingHappens; ... public void Bleh() { SomethingHappens.Raise(this, new MyImportantEventEventArgs { X=true }); } }
关于事件处理程序的另一个说明:我们可以简单地创建一个raise扩展方法,如下所示:
IDAL<T> GetDAL<T>(); // retrieve data access layer for entity T
然后,我们可以使用它引发事件:
该方法具有执行编码标准(使用EventHandler <>
)的添加优点。
一遍又一遍地编写相同的确切函数毫无意义。也许下一个版本的C最终将具有一个" InlineAttribute",可以将其放置在扩展方法上,并使编译器内联方法定义(这将使这种方法接近标准且最快)。
回答
编辑:在基于注释的扩展方法中删除了temp变量
回答
调试时,我们可以在Watch \ QuickWatch \ Immediate窗口中键入$ exception
并获取有关当前帧例外的所有信息。如果我们打开了第一次机会异常,这将非常有用!
回答
我不宽容,但令我惊讶的是,goto仍然围绕着鸭子进入的炮弹
RealProxy使我们可以为现有类型创建自己的代理。
这是超高级的,而且我还没有看到其他人使用过-这可能意味着它对大多数人来说确实没有那么有用-但这是值得一听的东西之一。
基本上,.NET RealProxy类使我们可以创建对另一种类型的透明代理。在这种情况下,透明意味着它看起来完全像是客户端的代理目标对象-但实际上不是:它是类的实例,它是从RealProxy派生的。
这使我们可以在客户端与在实际目标对象上调用的任何方法或者属性之间应用强大而全面的拦截和"中介"服务。将此功能与工厂模式(IoC等)结合使用,我们可以交还透明代理而不是真实对象,从而可以拦截对真实对象的所有调用,并在每次方法调用之前和之后执行操作。实际上,我相信这是.NET用于跨应用程序域,进程和计算机边界进行远程处理的功能:.NET拦截所有访问,将序列化信息发送到远程对象,接收响应,并将其返回给代码。
[Test, Category("ProfileEntity")] public void MyTest() { // this is the object that we want profiled. // we would normally pass this around and call // methods on this instance. DALToBeProfiled dal = new DALToBeProfiled(); // To profile, instead we obtain our proxy // and pass it around instead. DALToBeProfiled dalProxy = (DALToBeProfiled)EntityProfiler.Instance(dal); // or... DALToBeProfiled dalProxy2 = EntityProfiler<DALToBeProfiled>.Instance(dal); // Now use proxy wherever we would have used the original... // All methods' timings are automatically recorded // with a high-resolution timer DoStuffToThisObject(dalProxy); // Output profiling results ProfileManager.Instance.ToConsole(); }
也许有一个例子可以清楚地说明这是如何有用的:我为企业架构师的上一份工作创建了一个参考服务堆栈,它指定了该部门中所有新WCF服务的标准内部组成("堆栈")。该模型要求(例如)Foo服务的数据访问层实现IDAL <Foo>:
创建Foo,读取Foo,更新Foo,删除Foo。服务开发人员使用了提供的通用代码(由我提供),这些通用代码可以找到并加载服务所需的DAL:
该公司的数据访问策略经常受到性能挑战。作为一名架构师,我无法监视每个服务开发人员以确保他/她编写了高性能的数据访问层。但是我可以在GetDAL工厂模式下做的是创建一个对请求的DAL的透明代理(一旦DLL定位并加载了公共服务模型代码),并使用高性能的计时API来分析对任何方法的所有调用DAL。然后,对落后者进行排名只是通过减少总时间来排序DAL呼叫时间的问题。相对于开发概要分析(例如在IDE中)的优势在于,它也可以在生产环境中完成以确保SLA。
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)] // per FxCop public override IMessage Invoke(IMessage msg) { IMethodCallMessage msgMethodCall = msg as IMethodCallMessage; Debug.Assert(msgMethodCall != null); // should not be null - research Invoke if this trips. KWB 2009.05.28 // The MethodCallMessageWrapper // provides read/write access to the method // call arguments. MethodCallMessageWrapper mc = new MethodCallMessageWrapper(msgMethodCall); // This is the reflected method base of the called method. MethodInfo mi = (MethodInfo)mc.MethodBase; IMessage retval = null; // Pass the call to the method and get our return value string profileName = ProfileClassName + "." + mi.Name; using (ProfileManager.Start(profileName)) { IMessage myReturnMessage = RemotingServices.ExecuteMessage(_target, msgMethodCall); retval = myReturnMessage; } return retval; }
这是我为"实体分析器"编写的测试代码示例,这是为单行创建任何类型的性能分析代理的通用代码:
Constrained execution regions (CER's) exist to help a developer write her code to maintain consistency. The CLR doesn't guarantee that the developer's code is correct, but the CLR does hoist all of the runtime-induced failure points (ie, async exceptions) to either before the code runs, or after it has completed. Combined with constraints on what the developer can put in a CER, these are a useful way of making strong guarantees about whether your code will execute. CER's are eagerly prepared, meaning that when we see one, we will eagerly JIT any code found in its statically-discoverable call graph. If the CLR's host cares about stack overflow, we'll probe for some amount of stack space as well (though perhaps not enough stack space for any arbitrary method*). We also delay thread aborts until the CER has finished running.
同样,这可以让我们拦截目标对象上客户端调用的所有方法和属性!在RealProxy衍生的类别中,我们必须覆写Invoke:
回答
.NET可以使人着迷吗?唯一的限制是目标类型必须从MarshalByRefObject派生。我希望这对某人有帮助。
也有用,但不常用:约束执行区。
This event provides notification of uncaught exceptions. It allows the application to log information about the exception before the system default handler reports the exception to the user and terminates the application. If sufficient information about the state of the application is available, other actions may be undertaken — such as saving program data for later recovery. Caution is advised, because program data can become corrupted when exceptions are not handled.
BCL团队博客的引文:
当以原子方式对数据结构的多个字段进行编辑时,此功能很有用。因此,对对象进行事务处理很有帮助。
回答
而且CriticalFinalizerObject似乎被隐藏了(至少那些没有编写不安全代码的人)。
CriticalFinalizerObject保证垃圾回收将执行终结器。分配后,将预先准备终结器及其调用图。
string.Empty
AppDomain.UnhandledException事件也可以被隐藏。
回答
The fixed statement sets a pointer to a managed variable and "pins" that variable during the execution of statement.
我们可以看到,即使在此站点上,也有很多人在想为什么他们的应用程序无法启动,为什么崩溃等。AppDomain.UnhandledException
事件在这种情况下非常有用,因为它至少提供了以下可能性:记录应用程序失败的原因。
我知道这不是幻想(荒谬的奇怪),但是我一直都在使用它而不是""。
回答
而且它很隐蔽,直到有人告诉你它在那里。
固定陈述
[OperationContract, ServiceKnownType(typeof(Prism)), ServiceKnownType(typeof(Cuboid))] Shape GetShape();
该语句可防止垃圾回收器重新定位可移动变量。 Fixed也可用于创建固定大小的缓冲区。
栈分配
回答
stackalloc在堆栈上分配一个内存块。
##代码##回答
我们可以将几个属性放在一对方括号中:
不知道是否提到了这一页(11页!)
但是,当我们对将要序列化的类/对象进行版本控制时,类的" OptionalField"属性是惊人的。
回答
http://msdn.microsoft.com/zh-CN/library/ms229752(VS.80).aspx
从匿名方法访问局部变量使我们可以使用新的控制流逻辑包装几乎所有代码,而不必将该代码分解为另一个方法。在方法外部声明的局部变量可在方法内部使用,例如此处示例中的endOfLineChar
局部变量:
段落数量不匹配