Wie definiere ich eine generische Typbegrenzung für primitive Typen?

78

Ich habe die folgende Methode mit generischem Typ:

T GetValue<T>();

Ich möchte T auf primitive Typen wie int, string, float, aber nicht auf Klassentypen beschränken. Ich weiß, dass ich generisch für einen Klassentyp wie diesen definieren kann:

C GetObject<C>() where C: class;

Ich bin mir nicht sicher, ob und wie primitive Typen möglich sind.

David.Chu.ca
quelle
Ich denke , dass durch „Urtyp“ @ David.Chu.ca nicht verwalteten Typen bedeutet, dh int, floatusw. nicht Int32, Int64, Singleetc .. Obwohl classbezeichnet einen ref Typ „ aber nicht Klassentyp“ ist darauf hindeutet , den Unterschied zwischen unmanaged und managed Primitiven.
Mireazma

Antworten:

50

Sie können dies verwenden, um es auf Werttypen zu beschränken:

where C: struct

Sie erwähnen auch Zeichenfolge. Zeichenfolgen sind leider nicht zulässig, da es sich nicht um Werttypen handelt.

BKostenlos
quelle
2
aber nicht für Zeichenfolge, die
nullbar
5
Und natürlich können Sie damit jeden benutzerdefinierten Strukturtyp übergeben, nicht nur primitive Typen. Ich bin mir nicht sicher, ob es wirklich einen anderen Weg gibt, als Überladungen für alle eingebauten primitiven Typen zu definieren.
Matt Hamilton
1
Die Frage war für Primitive, nicht für Werttypen. Wie Sie in Ihrer Antwort erwähnt haben, ist das Zeichenfolgenprimitiv kein Werttyp, daher funktioniert es in dieser Hinsicht nicht. Außerdem können Sie zufällige Strukturen übergeben (wie @MattHamilton hervorhebt), die keine Grundelemente sind.
BrainSlugs83
Wenn ich eine Methode habe, n1 + n2bei der n1 und n2 beide vom Typ sind C, wird mir der Fehler Operator '+' cannot be applied to operands of type 'C' and 'C'
angezeigt
24

Eigentlich macht das den Job bis zu einem gewissen Grad:

public T Object<T>() where T :
   struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>

Um sich auf numerische Typen zu beschränken, erhalten Sie einige nützliche Hinweise zu den folgenden Beispielen, die für die ValueType- Klasse definiert wurden

Deko
quelle
15

Folgendes suchen Sie:

T GetObject<T>() where T : struct;
Joshua Belden
quelle
Verdammt! Ich hasse es, wenn mich jemand bis zum Anschlag schlägt. Schön BFree!
Joshua Belden
1
Wie wäre es mit einem primitiven, aber
nullbaren
4
@ David: String ist kein primitiver Typ. Es ist ein Referenztyp, der in einigen Fällen als primitiver Typ behandelt wird.
Samuel
Aber es gibt keine Möglichkeit, dynamisch abgerufene Objekte zu gießen, um diese structAnforderung zu erfüllen , oder?
Nyerguds
1
String ist ein Grundelement, aber kein Struktur- / Werttyp.
BrainSlugs83
11

Es gibt keine generische Einschränkung, die genau mit diesen Dingen übereinstimmt. Was möchten Sie eigentlich tun? Zum Beispiel können Sie es mit Laufzeitprüfungen wie einem statischen ctor umgehen (für generische Typen - für generische Methoden nicht so einfach) ...

Jedoch; Meistens sehe ich das, weil die Leute eines von folgenden wollen:

  • Elemente auf Gleichheit prüfen können: In diesem Fall verwenden EqualityComparer<T>.Default
  • Elemente vergleichen / sortieren können: In diesem Fall verwenden Comparer<T>.Default
  • um rechnen zu können: Verwenden Sie in diesem Fall die Unterstützung von MiscUtil für generische Operatoren
Marc Gravell
quelle
7

Was versuchst du eigentlich in der Methode zu tun? Es kann sein, dass Sie tatsächlich C benötigen, um IComparable oder eine andere Schnittstelle zu implementieren. In diesem Fall möchten Sie so etwas wie

T GetObject<T> where T: IComparable
David McEwing
quelle