2015-05-28 12 views
5

Data una classe:Cosa possono fare i generici cosa non puoi fare con la composizione?

public class TestMain 
{ 

} 

E due classi accettare istanze di questa classe, da uno a generici:

public class Test1<T> where T : TestMain 
{ 
    public Test1(T test) 
    { 

    } 
} 

e uno senza:

public class Test2 
{ 
    public Test2(TestMain test) 
    { 

    } 
} 

perché si sceglie uno sopra l'altro?

+0

Hai mai desidera avere tutte le classi derivate 'Employee' come membro della classe? –

+0

Leggi di C# generics: https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx –

+0

Sì, c'è una differenza, come puoi vedere. Il codice è diverso. Puoi spiegare cosa stiamo vedendo qui e cosa ti aspetti da tutte le dichiarazioni? – CodeCaster

risposta

5

In che caso è del tutto inutile ... ma diciamo di avere un metodo:

// In Test1<T> 
public List<T> GetList() 
{ 
} 

vs

// In Test2 
public List<TestMain> GetList() 
{ 
} 

e diciamo che avete un

public class TestSubclass: TestMain 
{ 
} 

Ora, è possibile:

List<TestSubclass> list1 = new Test1<TestSubclass>().GetList(); 

vs

List<TestMain> list2 = new Test2().GetList(); 

vedere i diversi tipi di ritorno? Se è utile o no dipende da come stai strutturando il tuo programma.

dirò un caso più comune è quando si aggiunge il new() tipo generico vincolo:

public class Test1<T> where T : TestMain, new() 

Ora in Test1 si potrebbe avere:

public T GetNew() 
{ 
    return new T(); 
} 

Si tratta di un "trucco" che Test2 impossibile, perché restituirebbe sempre un nuovo TestMain()

0

La differenza è che la variante generica assume t he tipo effettivo per T, dove l'altro espone solo TestMain.

Così dicono che ci si aggiunge una proprietà:

public class Test1<T> where T : TestMain 
{ 
    public T SomeProperty { get; private set; } 
    public Test1(T test) 
    { 
     SomeProperty = test; 
    } 
} 

public class Test2 
{ 
    public TestMain SomeProperty { get; private set; } 
    public Test2(TestMain test) 
    { 
     SomeProperty = test; 
    } 
} 

e dire che ci si introduce una classe derivata:

public class TestMain2 : TestMain 
{ 
    public string Foo2 { get; set; } 
} 

Poi nel Test2 non sarà in grado di accedere a Foo2 di TestMain2.SomeProperty senza casting, mentre nella classe generica T SomeProperty verrà esposto il tipo effettivo derivato con tutti i relativi membri.

0

Illustrazione generica.

dichiarazioni di classe

/// <summary> 
/// some base class 
/// </summary> 
public class BaseClass 
{ 
    public string Name { get; set; } 

    public BaseClass() 
    { 
     this.Name = "I'm basic class"; 
    } 
} 

/// <summary> 
/// inherited class 1 
/// </summary> 
public class CoolClass : BaseClass 
{ 
    public string Name { get; set; } 

    public CoolClass() 
    { 
     this.Name = "I'm cool class :)"; 
    } 
} 

/// <summary> 
/// inherited class 2 
/// </summary> 
public class SadClass : BaseClass 
{ 
    public string Name { get; set; } 

    public SadClass() 
    { 
     this.Name = "I'm sad class :("; 
    } 
} 

/// <summary> 
/// container 
/// </summary> 
/// <typeparam name="T"> element type </typeparam> 
public class UniversalContainer<T> where T : BaseClass 
{ 
    public List<T> Container { get; private set; } 

    public UniversalContainer() 
    { 
     this.Container = new List<T>(); 
    } 
} 

utilizzo

UniversalContainer<string> stringContainer = new UniversalContainer<string>();  // wrong 
UniversalContainer<BaseClass> baseContainer = new UniversalContainer<BaseClass>(); // right 
UniversalContainer<CoolClass> coolContainer = new UniversalContainer<CoolClass>(); // right 
UniversalContainer<SadClass> sadContainer = new UniversalContainer<SadClass>();  // right 

baseContainer.Container.Add(new BaseClass()); // right 
baseContainer.Container.Add(new SadClass()); // right 
baseContainer.Container.Add(new CoolClass()); // right 

coolContainer.Container.Add(new BaseClass()); // wrong 
coolContainer.Container.Add(new SadClass()); // wrong 
coolContainer.Container.Add(new CoolClass()); // right 

sadContainer.Container.Add(new BaseClass()); // wrong 
sadContainer.Container.Add(new SadClass());  // right 
sadContainer.Container.Add(new CoolClass()); // wrong 
+2

Puoi spiegare cosa illustra questo codice? Riguarda la co- e la contravarianza? – CodeCaster