2010-01-29

2010-01-27

Resharper:”Access to modified closure”

using System;

namespace ConsoleApplication1
{
    class Program
    {
        delegate void MyDelegate();
        static void Main()
        {
            MyDelegate d = null;
            string s;
            for (var i = 0; i < 10; i++)
            {
               s = i.ToString();
                d += () => Console.WriteLine(s);
            }
            d();
        }
    }
}

输出是什么?如果把s的定义放到循环内部呢?

using System;

namespace ConsoleApplication1
{
    class Program
    {
        delegate void MyDelegate();
        static void Main()
        {
            MyDelegate d = null;
            //string s;
            for (var i = 0; i <= 10; i++)
            {
                string s;
                s = i.ToString
();
                d += () => Console.WriteLine(s);
            }
            d();
        }
    }
}

 

第一种情况下,由于s是在循环外部定义的,所有的delegate都是共享的,所以,每循环一次,s增1,到最后,s变为10,最后执行d()的时候,用的都是同一个s,因此输出都是10。resharper 会提定义局部变量保存s的拷贝,如下,这样,每一次执行都会使用自己的copy,也就会输出0 1 2 3 ….10

using System;

namespace ConsoleApplication1
{
    class Program
    {
        delegate void MyDelegate();
        static void Main()
        {
            MyDelegate d = null;
            string s;
            for (var i = 0; i <= 10; i++)
            {
               s = i.ToString();
                string s1 = s;
                d += () => Console.WriteLine(s1);
            }
            d();
        }
    }
}

 

C#: Anonymous methods are not closures

The implementation of anonymous methods in C# and its consequences (part 1)

Resharper 提示”lambda expression to statement”

最近用上了resharper,实时对代码进行改进,碰到这么一个提示“lambda expression to statement”,那什么是lambda expression,什么是lambda statement?二者有什么区别?

Expression:
var exprBooks = books.Find(book => book.Author.Contains("Fowler"));


Statement:

var stmtBooks = books.Find(book => { return book.Author.Contains("Fowler"); });



A lambda statement contains braces and a function body, and can potentially have multiple lines like a standard delegate. A lambda expression is the single line with an implicit return



http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/18/expressions-and-lambdas.aspx

2010-01-26

.net links 2010/1/26

Use .NET Built-in Methods to Save Time and Headaches 

  TryParse() and File.WriteAllText(file, str) are really useful to me!

If you are using a loop, you're doing it wrong

if you can use Linq, do not use for and foreach

.Net Tip: Convert a String to Title Case

string helloWorld = "hello world haha ds s w";

Console.WriteLine(
    System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(helloWorld));

可以写个扩展方法

IEnumerable, IEnumerator, GetEnumerator()

如果想要自定义类型支持foreach,那么此类型必须实现IEnumerable 接口,然后在GetEnumerator()方法中返回实现IEnumerator接口的对象,实现Current,MoveNext,Reset方法。好消息是2.0中加入了yield关键字,一句yield return,编译器就会给你做剩下的事情

using System;
using System.Collections;

namespace ConsoleApplication2
{
public class Person
{
public Person(string fName, string lName)
{
FirstName = fName;
LastName = lName;
}

public string FirstName;
public string LastName;
}

public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];

for (int i = 0; i < pArray.Length; i++)
{
_people[i] = pArray[i];
}
}

IEnumerator IEnumerable.GetEnumerator()
{
//return new PeopleEnum(_people);
// and you can delete below PeopleEnum class
for (int i = 0; i < _people.Length; i++)
{
yield return _people[i];
}
}
}

public class PeopleEnum : IEnumerator
{
public Person[] _people;

// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;

public PeopleEnum(Person[] list)
{
_people = list;
}

public bool MoveNext()
{
position++;
return (position < _people.Length);
}

public void Reset()
{
position = -1;
}

public object Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}

class App
{
static void Main()
{
Person[] peopleArray = new Person[3]
{
new Person("Tom", "Cat"),
new Person("Jon", "Walker"),
new Person("Jet", "Li"),
};

People peopleList = new People(peopleArray);
foreach (Person p in peopleList)
Console.WriteLine(p.FirstName + " " + p.LastName);

}
}

或者是返回IEnumerable的方法

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
foreach (var p in Primes(100))
{
Console.WriteLine(p);
}
}

public static IEnumerable<int> Primes(int max)
{
yield return 2;
var found = new List<int> {3};
var candidate = 3;
while (candidate <= max)
{
var isPrime = found.TakeWhile(
prime => prime*prime <= candidate).All(prime => candidate%prime != 0);
if (isPrime)
{
found.Add(candidate);
yield return candidate;
}
candidate += 2;
}
}
}
}

Implementing iterators with yield statements

Behind the scenes of the C# yield keyword

2010-01-25

typeof() GetType() is

Suppose there are three Classes(type) Aninaml, Dog and Tree
and 3 instances animal dog and tree

if(dog is Animal) // true
dog.GetType() == typeof(Dog) // true

call to GetType gets resolved at runtime, while typeof is resolved at compile time.

throw ex 和 throw 一样么?

不一样,
throw 是输出整个stacktrack,考虑多层设计中,UI层有try catch, 逻辑层有 try catch, 数据层有try catch, 三者均使用 throw, 假设是在数据层出错,输出的exception 信息会显示这三层的throw point,由此可以知道 exception的源头在数据层;如果是在逻辑层出错,会输出两层的 throw point, 由此可知 exception 的源头在逻辑层
但是用 throw ex的话,会清空stacktrace,如上例,你只能看到UI层的exception,无法获知到底是发生在UI层还是逻辑层还是数据层

因此,总是使用throw 抛出原始 exception

JIT and NGEN

JIT, Just in time,即时编译,每次运行都会进行,会对代码进行优化
NGEN Native image generator,在运行前一次性的把代码转换为本地代码并存储为本地文件,会改善程序的启动性能,但对总体的性能,有可能提升,也有可能降低

Assembly.LoadFile() Assembly.LoadFrom() Assembly.Load()

1、Assembly.LoadFile()只载入相应的dll文件,比如Assembly.LoadFile(”a.dll”),则载入a.dll,假如a.dll中引用了b.dll的话,b.dll并不会被载入。Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,b.dll也会被载入。
2、用Assembly.LoadFrom()载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,比如a.dll有两个版本(版本1在目录1下,版本2放在目录2下),程序一开始时载入了版本1,当使用Assembly.LoadFrom(”2″”a.dll”)载入版本2时,不能载入,而是返回版本1。Assembly.LoadFile的话则不会做这样的检查,比如上面的例子换成Assembly.LoadFile的话,则能正确载入版本2。

3、Assembly.Load()方法参数为程序集的名称不包含扩展名

.net 4.0 中只保留了LoadFrom() 方法

http://msdn.microsoft.com/en-us/library/ee191568(VS.100).aspx


http://blog.csdn.net/nanqingfei/archive/2009/10/12/4659004.aspx

一个有用的C# Attribute: DebuggerDisplay


namespace ConsoleApplication2
{
[DebuggerDisplay("count ={Count}")]
public class Test
{
public int Count{ get; set;}
public string Name { get; set; }
public void Clear()
{
}
}
}


如上代码示例所示,该属性可以让对象在鼠标悬停时按格式显示Count字段的值,而不必点开对象查找,当对象有非常多的Property时,这个属性尤其有用