2009-01-18 7 views
13

Ich habe mir eine generische Collection-Klasse gebaut, die so definiert ist.T auf String und Int beschränken?

public class StatisticItemHits<T>{...} 

Diese Klasse kann nur mit int und string Werte verwendet werden. Dies wird jedoch

public class StatisticItemHits<T> where T : string, int {...} 

nicht kompilieren. Was mache ich falsch?

+0

Etwas sagt mir, Sie tun dies, weil Sie nicht, dass eine implizite Umwandlung realisiert besser wäre ... – Will

Antwort

13

Die Typeinschränkung ist für die Verwendung mit Schnittstellen vorgesehen. Ihr Beispiel schlägt vor, dass Sie Klassen zulassen möchten, die von int erben und Zeichenfolge, was irgendwie Unsinn ist. Ich schlage vor, dass Sie eine Schnittstelle entwerfen, die die Methoden enthält, die Sie in Ihrer generischen Klasse StatisticItemHits verwenden, und diese Schnittstelle als Einschränkung verwenden. Allerdings sehe ich Ihre Anforderungen hier nicht wirklich, vielleicht könnten Sie weitere Details zu Ihrem Szenario posten?

+0

Ja, nach einem zweiten Blick auf die Gestaltung nehmen, Sie sind völlig richtig über Ihren Ansatz. Danke für Ihre Hilfe. – Mats

1

Nicht möglich mit 'wo'. Du kannst kein 'oder' tun.

1

Sie können es nicht von der where-Klausel auf string und int beschränken. Sie können es im Konstruktor überprüfen, aber das ist wahrscheinlich kein guter Ort für die Überprüfung. Mein Ansatz wäre, die Klasse und abstrakt die Klasse Schöpfung in eine (halb-) Fabrik Muster zu spezialisieren:

class MyRestrictedGeneric<T> 
{ 
    protected MyRestrictedGeneric() { } 


    // Create the right class depending on type T 
    public static MyRestrictedGeneric<T> Create<T>() 
    { 
     if (typeof(T) == typeof(string)) 
      return new StringImpl() as MyRestrictedGeneric<T>; 

     if (typeof(T) == typeof(int)) 
      return new IntImpl() as MyRestrictedGeneric<T>; 

     throw new InvalidOperationException("Type not supported"); 
    } 


    // The specialized implementation are protected away 
    protected class StringImpl : MyRestrictedGeneric<string> { } 
    protected class IntImpl : MyRestrictedGeneric<int> { } 
} 

Auf diese Weise können Sie die Klasse Verwendung nur Zeichenfolge begrenzen und intern in Ihrer Klasse int.

+0

string ist kein Werttyp .. – driAn

+0

string ist ein Referenztyp, also hilft es nicht (ich denke) – tuinstoel

+0

Warum akzeptiert die Create-Methode ein Argument, das nie verwendet wird? – configurator

6

Sie könnten StatisticItemHits<T> eine abstrakte Klasse machen und zwei Unterklassen erstellen:

StatisticItemHitsInt : StatisticItemHits<int>{}

StatisticItemHitsString : StatisticItemHits<string>{}

Auf diese Weise kann es nur sein, ein int und String-Darstellung von StatisticItemHits

3

Wie andere haben Sie gesagt, Sie können auf diese Weise keine Typeinschränkungen verwenden. Was Sie tun können, ist von Ihrem Basistyp zu spezialisieren, wie folgt:

public class StatisticItemHits <T> { } 

public class StringStatisticItemHits : StatisticItemHits<string> { } 

public class IntegerStatisticItemHits : StatisticItemHits<int> { } 

Auch als Basisklasse generic ist, werden Sie nicht in der Lage sein, dies zu polymorph verwenden. Wenn Sie dies tun müssen, muss StatisticItemHits eine Schnittstelle implementieren und diese verwenden, um Instanzen zu referenzieren. Etwas wie:

public class StatisticItemHits <T> : IStaticticItemHits { } 

public interface IStatisticItemHits { } 
2

Vorausgesetzt, dass Sie nur zwei Typen hier haben würde ich hier stattdessen eine OO-Weg gehen und haben nur zwei Klassen für die beiden Typen.

Generika werden am besten verwendet, wenn die Umstände, unter denen sie angewendet werden können, generisch sind. Sie sind in solchen Situationen viel weniger nützlich.

Sie können nur auf Struktur oder Klasse-Typen beschränken, und ich glaube, dass es müssen basierte Einschränkungen numerisch oder Betreiber (zB unterstützen muss + =)

Int und String sind wirklich ganz anders, sicherlich anders als int und doppelt.Es würde nicht viel Sinn machen, wenn eine generische Klasse den unveränderlichen Referenztyp von String und den Werttyp von int unterstützen würde, ohne auch andere Typen zu unterstützen, die denen ähnlicher sind.

-2

einfach verwenden:

where TSource : IEquatable<string>