Ich möchte so etwas machen:
myYear = record.GetValueOrNull<int?>("myYear"),
Beachten Sie den nullbaren Typ als generischen Parameter.
Da die GetValueOrNull
Funktion null zurückgeben konnte, war mein erster Versuch folgender:
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : class
{
object columnValue = reader[columnName];
if (!(columnValue is DBNull))
{
return (T)columnValue;
}
return null;
}
Aber der Fehler, den ich jetzt bekomme, ist:
Der Typ 'int?' muss ein Referenztyp sein, um ihn als Parameter 'T' im generischen Typ oder in der generischen Methode verwenden zu können
Richtig! Nullable<int>
ist ein struct
! Also habe ich versucht, die Klasseneinschränkung in eine struct
Einschränkung zu ändern (und als Nebeneffekt kann ich nicht null
mehr zurückkehren):
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
Nun die Aufgabe:
myYear = record.GetValueOrNull<int?>("myYear");
Gibt den folgenden Fehler aus:
Der Typ 'int?' muss ein nicht nullbarer Werttyp sein, um ihn als Parameter 'T' im generischen Typ oder in der generischen Methode zu verwenden
Ist es überhaupt möglich, einen nullbaren Typ als generischen Parameter anzugeben?
IDataRecord
vonDbDataRecord
..Antworten:
Ändern Sie den Rückgabetyp in Nullable und rufen Sie die Methode mit dem Parameter nicht nullable auf
quelle
Verwenden Sie es einfach so:
quelle
GetValueOrDefault
, um zu verdeutlichen, dass esdefault(T)
eher zurückkehrt alsnull
. Alternativ können Sie eine AusnahmeT
auslösen lassen, wenn diese nicht nullwertfähig ist.Machen Sie einfach zwei Dinge mit Ihrem ursprünglichen Code - entfernen Sie die
where
Einschränkung und ändern Sie die letztereturn
vonreturn null
inreturn default(T)
. Auf diese Weise können Sie einen beliebigen Typ zurückgeben.Übrigens können Sie die Verwendung von vermeiden,
is
indem Sie Ihreif
Aussage in ändernif (columnValue != DBNull.Value)
.quelle
return default
ist jedoch ausreichend (Sie benötigen das nicht(T)
, der Compiler leitet es aus dem Signaturrückgabetyp ab).Haftungsausschluss: Diese Antwort funktioniert, ist jedoch nur für Bildungszwecke gedacht. :) James Jones 'Lösung ist wahrscheinlich die beste hier und sicherlich die, mit der ich gehen würde.
Das
dynamic
Schlüsselwort von C # 4.0 macht dies noch einfacher, wenn auch weniger sicher:Jetzt brauchen Sie keinen expliziten Typ, der auf der RHS angibt:
Tatsächlich brauchen Sie es überhaupt nicht!
value
wird nun ein int oder eine Zeichenfolge oder ein beliebiger Typ sein, der von der Datenbank zurückgegeben wurde.Das einzige Problem ist, dass dies Sie nicht daran hindert, nicht nullfähige Typen auf der LHS zu verwenden. In diesem Fall erhalten Sie eine ziemlich unangenehme Laufzeitausnahme wie:
Wie bei jedem Code, der
dynamic
Folgendes verwendet : Vorbehaltscodierer.quelle
Musste einfach etwas Unglaubliches ähnlich machen. Mein Code:
quelle
Ich denke, Sie möchten Referenztypen und Strukturtypen behandeln. Ich verwende es, um XML-Element-Zeichenfolgen in einen typisierteren Typ zu konvertieren. Sie können die nullAlternative mit Reflektion entfernen. Der Formatanbieter soll das kulturabhängige '.' oder ',' Trennzeichen in z. B. Dezimalstellen oder Ints und Doubles. Dies kann funktionieren:
Sie können es so verwenden:
quelle
Dies mag ein toter Thread sein, aber ich neige dazu, Folgendes zu verwenden:
quelle
Ich bin gerade selbst auf das gleiche Problem gestoßen.
... = reader["myYear"] as int?;
funktioniert und ist sauber.Es funktioniert mit jedem Typ ohne Probleme. Wenn das Ergebnis DBNull ist, wird null zurückgegeben, da die Konvertierung fehlschlägt.
quelle
int v=reader["myYear"]??-1;
oder einen anderen Standard anstelle von tun-1
. Dies kann jedoch zu Problemen führen, wenn der WertDBNull
...Ich weiß, dass dies alt ist, aber hier ist eine andere Lösung:
Jetzt ist es Ihnen egal, ob
T
es sich um einen Wert oder einen Referenztyp handelt. Nur wenn die Funktion true zurückgibt, haben Sie einen angemessenen Wert aus der Datenbank. Verwendung:Dieser Ansatz ist sehr ähnlich zu
int.TryParse("123", out MyInt);
quelle
Mehrere generische Einschränkungen können nicht im ODER (weniger restriktiv), sondern nur im UND (restriktiver) kombiniert werden. Dies bedeutet, dass eine Methode nicht beide Szenarien verarbeiten kann. Die generischen Einschränkungen können auch nicht verwendet werden, um eine eindeutige Signatur für die Methode zu erstellen. Daher müssten Sie zwei separate Methodennamen verwenden.
Sie können jedoch die generischen Einschränkungen verwenden, um sicherzustellen, dass die Methoden korrekt verwendet werden.
In meinem Fall wollte ich speziell, dass null zurückgegeben wird und niemals der Standardwert eines möglichen Werttyps. GetValueOrDefault = schlecht. GetValueOrNull = gut.
Ich habe die Wörter "Null" und "Nullable" verwendet, um zwischen Referenztypen und Werttypen zu unterscheiden. Und hier ist ein Beispiel für einige Erweiterungsmethoden, die ich geschrieben habe und die die FirstOrDefault-Methode in der System.Linq.Enumerable-Klasse ergänzen.
quelle
Der kürzere Weg:
Rückkehr
0
fürint
undnull
fürint?
quelle