Showing posts with label back to basic. Show all posts
Showing posts with label back to basic. Show all posts

2010-01-26

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,在运行前一次性的把代码转换为本地代码并存储为本地文件,会改善程序的启动性能,但对总体的性能,有可能提升,也有可能降低

一个有用的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时,这个属性尤其有用