Ресурс : Определенно выезд Gitcasts Scott Chacon, особенно разговор Railsconf .
Github является потрясающим и также имеет [приблизительно 113] полезные руководства .
IL, генерируемые компилятором C # (VS2008 sp1), будут почти эквивалентными для обоих случаев (даже в сборках отладки и выпуска).
Однако, если вам потребуется добавить параметризованные конструкторы, принимающие List
в качестве аргумента , все будет по-другому (особенно, когда вы создадите значительно большое количество объекты с такими конструкторами).
См. Следующие примеры, чтобы увидеть различия (вы можете скопировать и вставить в VS и построить его, чтобы увидеть IL с Reflector или ILDASM ).
using System;
using System.Collections.Generic;
namespace Ctors
{
//Tested with VS2008 SP1
class A
{
//This will be executed before entering any constructor bodies...
private List<string> myList = new List<string>();
public A() { }
//This will create an unused temp List<string> object
//in both Debug and Release build
public A(List<string> list)
{
myList = list;
}
}
class B
{
private List<string> myList;
//ILs emitted by C# compiler are identicial to
//those of public A() in both Debug and Release build
public B()
{
myList = new List<string>();
}
//No garbage here
public B(List<string> list)
{
myList = list;
}
}
class C
{
private List<string> myList = null;
//In Release build, this is identical to B(),
//In Debug build, ILs to initialize myList to null is inserted.
//So more ILs than B() in Debug build.
public C()
{
myList = new List<string>();
}
//This is identical to B(List<string> list)
//in both Debug and Release build.
public C(List<string> list)
{
myList = list;
}
}
class D
{
//This will be executed before entering a try/catch block
//in the default constructor
private E myE = new E();
public D()
{
try
{ }
catch (NotImplementedException e)
{
//Cannot catch NotImplementedException thrown by E().
Console.WriteLine("Can I catch here???");
}
}
}
public class E
{
public E()
{
throw new NotImplementedException();
}
}
class Program
{
static void Main(string[] args)
{
//This will result in an unhandled exception.
//You may want to use try/catch block when constructing D objects.
D myD = new D();
}
}
}
Примечание: Я не менял никаких флагов оптимизации при переключении на сборку Release.
Есть одно отличие:
Поля инициализируются немедленно перед конструктором объекта экземпляр вызывается, поэтому, если конструктор присваивает значение поле, оно перезапишет любое значение дается во время объявления поля. От MSDN :
Поведение обоих должно быть идентичным.
Однако вы можете рассмотреть крайний случай IL - Bloat . IL для инициализаторов полей вставляется в верхнюю часть каждого ctor. Из этого следует, что если у вас есть много инициализаторов полей и много перегруженных ctors , тот же раздел IL будет добавлен к IL перегрузки ctor. В результате общий размер вашей сборки может увеличиться по сравнению со случаем, когда вы используете цепочку конструкторов или делегируете общую функцию Initialize ()
(где повторяющийся IL будет вызовом метода). следовательно, для этого конкретного сценария инициализаторы полей будут относительно более слабым выбором.
Вы можете проверить это с помощью отражателя в двоичном файле для этого фрагмента кода
public class MyClass2
{
private List<int> whack = new List<int>();
// lots of other field initializers
public MyClass2()
{
Console.WriteLine("Default ctor");
}
public MyClass2(string s)
{
Console.WriteLine("String overload");
}
// lots of other overload ctors
}
При инициализации в конструкторе, я думаю, было бы проще перехватывать и обрабатывать исключения, если это необходимо.
В MyClass1 кто-то может переопределить конструктор и вызвать проблемы.
Коды эквивалентны, потому что компилятор помещает инициализацию в каждый конструктор, который у вас есть во втором случае, преимущество второго случая заключается в том, что программист не будет думать об инициализации полей, когда он добавит новый конструктор через год писать этот класс :)
В C # практически нет разницы между вашими двумя примерами. Но разработчик стремится инициализировать свои поля в конструкторе, потому что он менее подвержен ошибкам.