2010-11-08 12 views
13

Gibt es eine Möglichkeit, einen Standardtyp für einen Parameter T eines generischen, so etwas wie zu bieten:Wie auch immer ein generischer Parameter zu einem bestimmten Typ?

class Something<T = string> 
{ 
} 

ich es nicht viele gute Gründe dafür wissen, aber ich möchte den Client-Code andeuten welchen Typ sollte er vorzugsweise verwenden?

Eine andere Sache, kann ich den generischen Typ auf ValueType beschränken? Ich habe gerade gesehen, dass Sie nicht können, aber trotzdem würde ich gerne wissen warum. Jeder hat eine Ahnung?

Danke!

+0

Diese ist standardmäßig nicht möglich. – Vercas

+1

Warum sagen Sie, dass Sie einen generischen Typ nicht auf einen Werttyp beschränken können, wenn fast jede Antwort hier zeigt, wie es gemacht wird? (Nicht über 'ValueType', sondern über das Schlüsselwort' struct'.) – stakx

+0

@stakx Ich sagte standardmäßig. (Wie er versuchte - durch "default" ing der Wert.) – Vercas

Antwort

18

Ok, ich nehme an, Sie die Klasse haben:

class Something<T> 
{ 

} 

Nun, möchten Sie vielleicht eine andere Klasse:

class Something : Something<string> 
{ 
    // NO MORE CODE NEEDED HERE! 
} 

Dies ist der einzige und der beste Weg.
Also wenn man Something verwendet, wird er tatsächlich Something<string> verwenden.

+2

Dies funktioniert (fsvo "funktioniert", nicht, dass ich es allgemein empfehlen würde), weil 'Etwas' und' Etwas <'> '(und' Irgendetwas <','> 'ist immer noch anders) zwei * verschiedene * Klassen sind (stellen Sie sich den Fall von' system.collections.IEnumerable vor 'und' systems.collections.generic.IEnumerable '- dies unterscheidet sich von Java, wo im Wesentlichen nur ein" minimierter "Typ erlaubt ist. Auf der anderen Seite haben Sie jetzt zwei * verschiedene * Typen :-) –

+0

Eine andere Alternative könnte sein: 'using Something = foo.Something ;' Allerdings ist das verwendete Konstrukt nur in wenigen Fällen verfügbar (vor Klassen oder am Anfang von eine äußere Klasse vor Mitgliedern usw.) und * wird nicht extern als Typ/Alias ​​dargestellt. –

+0

@pst Ich würde das anstelle dessen verwenden, was ich gepostet habe, aber ich dachte, dass er vielleicht mehr brauchen könnte. – Vercas

3

Sie können das Schlüsselwort where verwenden, um die spezifischen Typen einzuschränken, die als Typparameter verwendet werden können.

Zum Beispiel könnten Sie Ihre Klasse nur generische Typparameter zu annehmen, wenn der Typ implementiert die IComparable Schnittstelle:

class Something<T> where T : IComparable 
{ 
} 

Oder, wie Sie erwähnt haben, Sie T einschränken kann ein Werttyp sein where T : struct unter Verwendung :

class Something<T> where T : struct 
{ 
} 

Siehe MSDN Artikel über Constraints on Type Parameters für weitere Informationen. Hoffe das hilft!

2

Nach dem docs können Sie T einschränken Wert Typ zu sein mit dem where Stichwort

where T: struct 

Klassendeklaration würde dann wie folgt aussehen:

class Something<T> where T: struct { 
    ... 
} 

Obwohl string ist kein Werttyp und Sie können es nicht mit einer solchen Einschränkung verwenden. Vielleicht wäre IComparable besser, wenn Sie auch den string Typ verwenden möchten.

Wie für die Angabe des Standardtyps, glaube ich nicht, dass es möglich ist.

0
class Something<T> where T : string 
{ 
}; // eo class Something<> 
+0

Sie können nicht von String erben, also wäre die einzige Option, 'var s = new Something ;' zu deklarieren. Alles andere wird zu einem Fehler. – Vercas

2

Ich glaube nicht, dass es einen Weg gibt, es auf einen bestimmten Typ zu setzen, aber Sie könnten das als Kommentar in die XML-Dokumentation einfügen. Was auf einen Wert Typ als eine Einschränkung, können Sie dieses Verhalten erhalten, indem Sie Ihre allgemeine Deklaration wie folgt:

class MyGeneric<T> where T : struct 
{ 
    ... 
} 
+0

And +1 für die Beantwortung der 2. Frage: p –

+1

Wenn Sie Zeichenfolgen möchten, benötigen Sie möglicherweise 'where T: class', da' System.String' eine Klasse ist. – Vercas

+0

@Vercas - Korrekt oder Sie erhalten den Fehler: 'Der Typ 'Zeichenfolge' muss ein nicht Nullable Werttyp sein, um es als Parameter 'T' im generischen Typ oder Methode 'Something '' – atconway

0

Sie benötigen eine Unterklasse.Vor kurzem musste ich so etwas, das ist meine Lösung:

string param1 = "Hello"; 
    Concrete c = new Concrete(); 
    c.Do(param1); 
    c.Do(param1, 123); 
    c.Do(param1, (int?)null); 
    /* Result: 
    param1: Hello 
    param2 == null 
    ============================================= 
    param1: Hello 
    param2 = 123 
    ============================================= 
    param1: Hello 
    param2 == null 
    ============================================= 
    */ 

Ich ziehe es null Standardwerte zu verwenden, da ich diese Zeilen lesen:

public abstract class MyGenericClass<T1, T2> 
    { 
     public abstract void Do(T1 param1, T2 param2); 
    } 

    public class Concrete : MyGenericClass<string, int?> 
    {   
     public override void Do(string param1, int? param2 = null) 
     { 
      Console.WriteLine("param1: {0}", param1); 

      if (param2 == null) 
       Console.WriteLine("param2 == null"); 
      else 
       Console.WriteLine("param2 = {0}", param2); 

      Console.WriteLine("============================================="); 
     }   
    } 

Sie die Methode aufrufen kann C# In Depth – Optional Parameters and Named Arguments

Verwandte Themen