2009-07-30 11 views
6

Ich habe die folgende Methode:Wie erhält der C# -Compiler generische Typen?

public TResult Get<TGenericType, TResult>() 
          where TGenericType : SomeGenericType<TResult> 
          where TResult : IConvertible { 
    //...code that uses TGenericType... 
    //...code that sets someValue... 
    return (TResult) someValue; 
} 

Gerade jetzt, ein Benutzer dieses Verfahrens hat es wie folgt zu verwenden:

//Notice the duplicate int type specification 
int number = Get<SomeGenericType<int>, int>(); 

Warum muss ich TResult im Verfahren defintion angeben? Der Compiler kennt TResult bereits, da ich es in TGenericType angegeben habe. Im Idealfall (wenn die C# Compiler ein wenig schlauer war), würde meine Methode wie folgt aussehen:

public TResult Get<TGenericType>() 
          where TGenericType : SomeGenericType<TResult> 
          where TResult : IConvertible { 
    //...code that uses TGenericType... 
    //...code that sets someValue... 
    return (TResult) someValue; 
} 

So könnte der Benutzer einfach nur es wie folgt verwendet werden:

//Much cleaner 
int number = Get<SomeGenericType<int>>(); 

Gibt es eine Möglichkeit zu tun Was ich machen will; was ich vorhabe zu tun?

+0

Ich denke, einige Qualifier wie * dumm * aus Frage Beschreibung entfernen wird helfen. – EFraim

+0

Es ist der Compiler, der dumm ist, oder? ;) Ich entfernte den fremden Kommentar. Das ist eigentlich eine vernünftige Frage ohne sie. –

+0

Da Sie darauf geantwortet haben, dass es nicht möglich ist, nur einige der Typparameter zu verwenden, sollten Sie Ihre Frage vielleicht neu formulieren, was Sie erreichen möchten. So wie es aussieht, lautet Ihre Frage "Wie kann ich den C# -Compiler dazu bringen, Code zu kompilieren, der gegen die Definition der C# -Sprache verstößt?" Als solche sollte es als "keine echte Frage" geschlossen werden. –

Antwort

8

Die C# -Spezifikation erlaubt nicht, die Hälfte der Argumente vom Typ abzuleiten. Sie sollten entweder den Compiler veranlassen, alle Typargumente abzuleiten (was in Ihrem Fall nicht immer der Fall ist) oder alle manuell angeben.

UPDATE (auf Kommentar antworten): Während ich nicht im C# -Team bin, um eine absolute Antwort auf Ihre Frage zu geben, ist meine Spekulation, dass die Komplexität der Überladung Auflösung (das ist schon überwältigend; Sie wissen Wenn Sie diesen Abschnitt der C# -Spezifikation lesen würden, würde dies erheblich zunehmen, wenn Sie zulassen wollten, dass die Hälfte der Typen abgelesen wird und die Hälfte nicht (vor allem, wenn Sie Methoden nur durch die Anzahl der generischen Argumente überladen können).

+0

Aber warum haben sie das in der C# Spezifikation spezifiziert? Es ist nicht so, als ob irgendetwas unsicher wäre. –

+0

Sehen Sie sich einige der C++ - Regeln an, einschließlich der teilweisen Spezialisierung von Vorlagen und der Funktionsweise von Zugriffsspezifizierern. Gewöhnlich läuft alles reibungslos, aber da und da lauern immer wieder Fehler. Da eine der Ideen hinter Java und C# darin bestand, die Komplikation von C++ zu vermeiden und stattdessen ein wenig Unannehmlichkeiten zu akzeptieren, ist dies genau richtig. –

1

Es hängt ...

Wenn Sie nur SomeGenericType<TResult> verwenden, können Sie tun:

public TResult Get<TResult>() where TResult : IConvertible { 
    SomeGenericType<TResult> myInstance = ... 
    //...code that sets someValue... 
    return (TResult) someValue; 
} 

Es nicht unbedingt ein Weg ist, da die erste Art zu setzen, in diesem Fall . Da Ihr Beispiel nicht explizit einen SomeGenericType<TResult> als Parameter eingibt, schlägt dies vor, dass dies möglich wäre.

Andernfalls müssen Sie alle generischen Argumente vollständig angeben. Leider ist das genau so in C#.

+0

Sicher, aber ich muss SomeGenericType in der Methode verwenden. Ich werde meinen Beispielcode aktualisieren, um das klarzustellen. –

+0

Ja, aber sieh dir meinen Code an - solange er nicht als Parameter für die Methode übergeben wird, kannst du SomeGenericType in der Methode verwenden (zB: wenn du eine in der Methode konstruierst). Da Sie TResult kennen, funktioniert das gut. Wie ich schon sagte - es kann in einigen Fällen funktionieren ... –

+0

Sorry, ich meinte, ich brauche TGenericType (siehe meinen aktualisierten Beispielcode). –