Tip 1: 访问其他项目中的internal方法
在项目B中访问项目A的访问修饰符为:internal 的方法,示例如下:(MyTestAssembly为写在A项目中Assembly.cs中B项目名称。不支持private/protected)
//Make the internals visible to the test assembly [assembly: InternalsVisibleTo("MyTestAssembly")]
Tip 2: 使用Tuples
在项目中,当一个方法返回一个值时,直接返回,当返回两个值时,可以使用KeyValuePair,返回多个值时,经常使用POCOClass来封装一下,.NET Framework 4.0引入了Tuples类,可实现方法间多值的传递。
public Tuple<int, string, string> GetEmployee() { int employeeId = 1001; string firstName = "Rudy"; string lastName = "Koertson"; //Create a tuple and return return Tuple.Create(employeeId, firstName, lastName); }
Tip 3: Yield关键字
我们经常在过滤筛选集合时,使用临时集合变量来存储过程中的变化。下面的方法使用了临时变量来获取Value>100的集合。
public List<int> GetValuesGreaterThan100(List<int> masterCollection) { List<int> tempResult = new List<int>(); foreach (var value in masterCollection) { if (value > 100) tempResult.Add(value); } return tempResult; }
其实,为了避免产生临时变量增加内存消耗,我们可以使用Yield关键字,如下:
public IEnumerable<int> GetValuesGreaterThan100(List<int> masterCollection) { foreach (var value in masterCollection) { if (value > 100) yield return value; } }
当然,我们也可以使用 LINQ 来实现。
Tip 4: 告诉别人,你的方法要过时了
当由于重构或者其他的原因,需要放弃现有方法的使用,但又需要给使用者一些缓冲时间,并且提示使用者使用新得方法,可以使用Obsolete属性,示例如下:
[Obsolete("This method will be deprecated soon. You could use XYZ alternatively.")] public void MyComponentLegacyMethod() { //Here is the implementation }
如果你想使用者出现编译错误,则可以设置Obsolete的boolean类型参数为true:
[Obsolete("This method is deprecated. You could use XYZ alternatively.", true)] public void MyComponentLegacyMethod() { //Here is the implementation }
Tip 5: 注意LINQ查询的延迟执行
在.NET中,当我们使用LINQ查询时,实际上我们在使用它的返回结果变量时,LINQ才开始执行查询操作。这也就是说,我们频繁使用结果变量,意味着频繁执行LINQ查询操作。
为了避免重复执行LINQ查询,造成性能损耗,我们及时将查询结果转换。如下:
public void MyComponentLegacyMethod(List<int> masterCollection) { //Without the ToList this linq query will be executed twice because of the following usage var result = masterCollection.Where(i => i > 100).ToList(); Console.WriteLine(result.Count()); Console.WriteLine(result.Average()); }
Tip 6: 使用Explicit关键字定制实体转换
使用Explicit关键字可以自定义实体转换。示例如下:
class Program { static void Main(string[] args) { ExternalEntity entity = new ExternalEntity() { Id = 1001, FirstName = "Dave", LastName = "Johnson" }; MyEntity convertedEntity = (MyEntity)entity; } } class MyEntity { public int Id { get; set; } public string FullName { get; set; } public static explicit operator MyEntity(ExternalEntity externalEntity) { return new MyEntity() { Id = externalEntity.Id, FullName = externalEntity.FirstName + " " + externalEntity.LastName }; } } class ExternalEntity { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
Tip 7: Retaining the Exact Stack Trace
In a C# program in the catch block if you throw the exception as given below and the error has occurred in the method ConnectDatabase, the thrown exception stack trace will only show that the error has occurred in the RunDataOperation method. It would have lost the actual error source.
public void RunDataOperation() { try { Intialize(); ConnectDatabase(); Execute(); } catch (Exception exception) { throw exception; } }
To retain the actual stack trace throw as shown below.
public void RunDataOperation() { try { Intialize(); ConnectDatabase(); Execute(); } catch (Exception) { throw; } }
Tip 8: Flags Attribute - Enum Grouping
Decorating the enum with the Flags attribute in C# will enable the enum as bit fields. This allows us to group the enum values. Here is a sample piece of C# code.
class Program { static void Main(string[] args) { int snakes = 14; Console.WriteLine((Reptile)snakes); } } [Flags] enum Reptile { BlackMamba = 2, CottonMouth = 4, Wiper = 8, Crocodile = 16, Aligator = 32 }
输出为: "BlackMamba, CottonMouth, Wiper"。
Tip 9: 限制泛型的基础类型
我们在设计泛型时,想将T设定在某个范围,代码如下:(设定可为接口、类,也可以设定多个,还有new(),表示可实例化)
class MyGenricClass<T> where T : IMyInterface { //Body of the class come in here }
方法级:
class MyGenricClass { public void MyGenericMethod<T>(T t) where T : IMyInterface { //Generic implementation goes in here } }
Tip 10: IEnumerable的只读设置
在程序类的设计中,一般设置属性的只读只需设置get方法为public,不写或者设置set方法为private,就可以保证该属性的只读。但是这种方法对于引用类型(除string)来说并不可行。示例代码如下:
class Program { static void Main(string[] args) { MyClass myClass = new MyClass(); ((List<string>)myClass.ReadOnlyNameCollection).Add("######From Client#####"); myClass.Print(); } } class MyClass { List<string> _nameCollection = new List<string>(); public MyClass() { _nameCollection.Add("Rob"); _nameCollection.Add("John"); _nameCollection.Add("Jummy"); _nameCollection.Add("Derek"); } public IEnumerable<string> ReadOnlyNameCollection { get { return _nameCollection.AsEnumerable(); } } public void Print() { foreach (var item in ReadOnlyNameCollection) { Console.WriteLine(item); } } }
上面代码成功的新增Name。如何才能保证IEnumerable只读呢,使用 AsReadOnly 替代 AsEnumerable。
public IEnumerable<string> ReadOnlyNameCollection { get { return _nameCollection.AsReadOnly(); } }
Happy reading!
FROM <http://www.developer.com/net/top-10-tips-for-c-programmers.html>