2016-10-21 6 views
6

Sagen, ich habe den folgenden Typ:Wie deklariere ich ein Array mit einem generischen Typ?

public class Field<T> 
{ 
    public string Name { get; set; } 
    public T Value { get; set; } 
} 

Wie kann ich eine Variable deklarieren, die ein Array solcher Felder enthalten? Ich habe versucht, die folgenden:

var customFields = new Field[] 
{ 
    new Field<string> { Name = "nickname", Value = "Bob" }, 
    new Field<int> { Name = "age", Value = 42 }, 
    new Field<DateTime> { Name = "customer_since", Value = new DateTime(2000, 12, 1) } 
}; 

aber ich erhalte die folgende Compiler-Ausnahme:

Mit dem generischen Typ 'Field' erfordert 1 Typ Argumente

Ich habe auch versucht var customFields = new Field<object>[] aber Ich erhalte folgende Fehler:

Kann den Typ 'Field' nicht implizit in 'F konvertieren ield‘

kann nicht implizit konvertiert Typ‚Field‘auf‚Field‘

nicht implizit Kann Typ konvertieren‚Field‘auf‚Field‘

+4

Jeder generische Typ ist ein * anderer Typ *. Daher versuchen Sie, ein Array von Instanzen unterschiedlicher Typen zu erstellen. Das ist nicht möglich. Es ist so, als würde man versuchen, ein Array zu erstellen, das 'string'- und' int'-Werte speichert. Sie können jedoch [Kovarianz] (https://msdn.microsoft.com/en-us/library/dd799517 (v = vs.110) .aspx) betrachten. –

Antwort

12

Wie Matias sagte, es kann nicht so gemacht werden, weil Field<int> und Field<string> sind völlig verschiedene Arten. Was können Sie tun, ist:

erstellen Basis Field die nicht generisch ist:

public class Field 
{ 
    public string Name { get; set; } 
} 

public class Field<T> : Field 
{ 
    public T Value { get; set; } 
} 

Und dann:

var customFields = new Field[] 
{ 
    new Field<string> { Name = "nickname", Value = "Bob" }, 
    new Field<int> { Name = "age", Value = 42 }, 
    new Field<DateTime> { Name = "customer_since", Value = new DateTime(2000, 12, 1) } 
}; 

Wie Matias ein Downcasting kommentiert werden benötigt, um die Value des bekommen verschiedene Typen. Wenn es für jeden unterschiedlichen Typ von Value eine spezifische Logik gibt, die ausgeführt werden soll, ist es ein guter Weg, das Entwurfsmuster Factory zu verwenden. Die Fabrik wird für jede Field eine korrekte "FieldHandler<T>" zurückgeben, die downcast wird, den Vorgang ausführen und zurückgeben, was benötigt wird.

+5

FYI: Sie müssen den generischen Typ verkleinern, um die Value-Eigenschaft eines Elements zu erhalten. –

+0

@MatiasCicero - Ya ... Das ist wahr .. –

+0

Sehr gute Idee! Wie Matias sagte, muss ich casten, um den Wert zu erhalten, aber in meinem speziellen Fall keine große Sache, da ich nur string, int und DateTime unterstütze. Übrigens, weiß jemand, ob ich T nur auf diese drei Typen beschränken kann? Etwas in der Art von: 'where T: string, int, DateTime' – desautelsj

2

Eine andere Sache, die Sie tun können, ist einfach die gemeinsame Basisklasse für alle diese Typen - Objekt.

class Field 
{ 
    public string Name { get; set; } 
    public Object Value { get; set; } 
} 
var customFields = new Field[] 
{ 
    new Field { Name = "nickname ", Value = "Bob" }, 
    new Field { Name = "age", Value = 42 }, 
    new Field { Name = "customer_since", Value = new DateTime(2000, 12, 1) } 
}; 

Dies würde jedoch eine Art Handhabung für den Verbraucher von Custom werden ausgelagert, sondern sollte in Ordnung sein, wenn die Werttypen mit einem bestimmten Feldname zugeordnet bekannt sind.

+0

Ich stimme Ihrer ersten Annäherung zu, und deshalb bekam sie mein upvote aber die Ausgabe an der Unterseite - in diesem Fall .. warum nicht, Generika zu verwenden? .. :) –

+0

Sie haben Recht! Ich wollte nur für den Fall von Whitelist-Typen hinzufügen, aber selbst mit Generics können Sie die Verwendung von ': Wobei T: [Typen erlaubt]' einschränken. Danke für deine Unterstützung :) –

Verwandte Themen