Inicializaci třídy pole v opravit, nebo v konstruktoru třídy

hlasů
8

Mám třídu s polem, který má být inicializován při inicializaci objektu, jako je seznam, který má být vytvořen před objekty mohou být přidány / z ní odstraněny.

public class MyClass1
{
    private List<MyOtherClass> _otherClassList;

    public MyClass1()
    {
        this._otherClasslist = new List<MyOtherClass>();
    }
}


public class MyClass2
{
    private List<MyOtherClass> = new List<MyOtherClass>();

    public MyClass2()
    {
    }
}

Jaký je rozdíl mezi těmito dvěma třídami, a proč byste si vybrat jednu metodu nad druhým?

I obvykle nastavit pole v konstruktoru, jak je v MyClass1, protože považuji za snazší být schopni podívat se na jednom místě vidět všechny ty věci, co se stane, když je tento objekt je instance, ale je tam nějaký případ, kdy je lepší inicializovat pole přímo jako v MyClass2?

Položena 21/07/2009 v 04:45
zdroj uživatelem
V jiných jazycích...                            


7 odpovědí

hlasů
0

Kódy jsou rovnocenné, protože kompilátor dát inicializace v každém konstruktoru máte v druhém případě ve prospěch druhého případu je, že programátor nebude myslet inicializovat pole, když přidám nový konstruktor po roce zápisu tuto třídu :)

Odpovězeno 21/07/2009 v 04:52
zdroj uživatelem

hlasů
0

V jazyce C # není prakticky žádný rozdíl mezi svými dvěma příklady. Ale developer má tendenci inicializovat svá pole v konstruktoru, protože méně náchylné k chybám.

Odpovězeno 21/07/2009 v 04:54
zdroj uživatelem

hlasů
2

Při inicializaci v konstruktoru bych si, že by bylo jednodušší zachytit a zpracovat výjimky, jestliže je to nutné.

Odpovězeno 21/07/2009 v 05:13
zdroj uživatelem

hlasů
5

ILS vysílané C # kompilátoru (VS2008 SP1) bude téměř stejná pro obou případech (a to i v ladění a sestavení vydání).

Nicméně, pokud budete muset přidat parametrické konstruktérů, které berou jako argument , to bude jinak (zejména pokud budete vytvářet výrazně velký počet objektů s takovými konstruktérů). List<MyOtherClass>

Viz následující příklady vidět rozdíly (můžete zkopírovat a minulost VS a postavit ji vidět ILS s reflektorem nebo 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();
        }
    }
}

Poznámka: Při přepnutí na verzi sestavení jsem neměnil žádnou optimalizační příznak.

Odpovězeno 21/07/2009 v 05:59
zdroj uživatelem

hlasů
1

V MyClass1 mohl někdo přepsat konstruktor a způsobit problémy.

Odpovězeno 21/07/2009 v 06:22
zdroj uživatelem

hlasů
3

Je zde jeden rozdíl:

Pole jsou inicializovány těsně před konstruktoru pro instanci objektu se nazývá, takže v případě, že konstruktor přiřadí hodnotu pole, přepíše jakoukoliv hodnotu uvedenou v deklaraci pole. Z MSDN :

Odpovězeno 21/07/2009 v 06:34
zdroj uživatelem

hlasů
3

Chování-moudrý jak by měly být shodné.
Nicméně něco, co budete chtít, aby zvážila, je okrajový případ IL - nafouknout . IL pro pole Inicializátory je vložen do horní části každého ctor. A z toho vyplývá, že pokud máte mnoho polí inicializátory a mnoho přetížených ctors , stejná část IL předponou k ctor přetížení IL. Výsledkem je, že celková velikost sestavě by mohlo jít až v porovnání s případem, kdy používáte konstruktor řetězení nebo delegáta ke společné Initialize()funkci (kde zopakoval IL by volání metody). tedy v tomto konkrétním případě, polní inicializátory by byl relativně slabší volba.

To lze ověřit s reflektorem na binární tohoto fragmentu kódu

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
   }
Odpovězeno 21/07/2009 v 07:06
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more