2012-10-15 11 views
5

Wenn die folgende Methode:Typ Prüfung auf Nullable <int>

static void DoSomethingWithTwoNullables(Nullable<int> a, Nullable<int> b) 
{ 
    Console.WriteLine("Param a is Nullable<int>: " + (a is Nullable<int>)); 
    Console.WriteLine("Param a is int   : " + (a is int)); 
    Console.WriteLine("Param b is Nullable<int>: " + (b is Nullable<int>)); 
    Console.WriteLine("Param b is int   : " + (b is int)); 
} 

Wenn ich nenne diese Methode mit null als Parameter, die Typprüfung für diesen Parameter false zurückgibt. Zum Beispiel dieses Code

DoSomethingWithTwoNullables(5, new Nullable<int>()); 

Ergebnisse in dieser Ausgabe:

Param a is Nullable<int>: True 
Param a is int   : True 
Param b is Nullable<int>: False 
Param b is int   : False 

Gibt es eine Möglichkeit die Typinformationen zu erhalten, wenn eine Nullable und vorbei null verwenden? Ich weiß, dass die Überprüfung des Typs in diesem Beispiel nutzlos ist, aber es veranschaulicht das Problem. In meinem Projekt übergebe ich die Parameter an eine andere Methode, die ein params object[] Array verwendet und versucht, den Typ der Objekte zu identifizieren. Diese Methode muss verschiedene Dinge für Nullable<int> und Nullable<long> tun.

Antwort

5

Gehen Sie direkt zu dem zugrunde liegenden Problem, nein, Sie können dies nicht tun. Eine Null Nullable<int> hat genau die gleiche geboxte Darstellung wie eine Null Nullable<long> oder tatsächlich eine 'normale' Null. Es gibt keine Möglichkeit zu sagen, welcher Typ von Null es ist, da die zugrundeliegende Darstellung einfach nur aus Nullen besteht. Weitere Informationen finden Sie unter Boxing Nullable Types.

+0

Weil b zuerst mit "int" eingerahmt wird, ergibt dies eine Nullreferenz. – usr

+0

Vermutlich könnten Sie {} catch {} versuchen, es zu testen, also gibt es eine Möglichkeit, das herauszufinden. Ich wette mit Reflektion, dass du einen Schritt weiter gehen und es polieren könntest. Vielleicht initialisiere ich eine neue Instanz, die ihr einen Standardwert geben soll, und mache 'typeof (variable.value)'? – NibblyPig

+0

@SLC: Sie können nicht. Es ist nur eine Nullreferenz ohne Typinformation. – usr

0

Leider zeigt null nicht auf einen bestimmten Speicherort, und daher gibt es keine Metadaten, die Sie zuordnen können, um den Typ zu suchen. Daher können Sie keine zusätzlichen Informationen über die Variable erhalten.

3

konzeptionell new Nullable<int>istnull.

Wenn wir verallgemeinern, zu vergessen, über Nullable<T>:

string s = null; 
bool b = s is string; 

wir false bekommen. false ist der erwartete Wert für eine Typprüfung auf einen null Wert.

+1

Was, wenn er 'b = 3;'? Wenn es eine Zeichenkette ist, dann würden Sie einen Fehler erhalten, aber wenn es ein Int oder ein Nullwert int wäre, würden Sie keinen Fehler bekommen? – NibblyPig

1

Sie können versuchen, Reflection zu verwenden, um dies zu erreichen. Relevant article here.

+1

Sie können keine Reflektion verwenden. Der Aufruf von 'GetType()' für einen NULL-Verweis wird 'NullReferenceException' auslösen. Mit dem Nullverweis ist kein Typ verknüpft. Der verlinkte Artikel basiert auf Typen und nicht auf Referenzen auf Objekte (die in diesem Fall null sein können). –

+0

@Martin ist richtig. –

0

Wenn ich die Frage nicht falsch verstehe, können Sie den Typ mit GetType() abrufen. Zum Beispiel

int? myNullableInt = null; 
Console.WriteLine(myNullableInt.GetValueOrDefault().GetType()); 

Wenn myNullableInt null ist, wird ein Standardwert zurückgegeben werden. Überprüfen Sie den Typ dieses zurückgegebenen Werts, und in diesem Fall wird System.Int32 zurückgegeben. Sie können eine If..else/Switch Prüfung auf den zurückgegebenen Typ durchführen, um die entsprechende Aktion durchzuführen.

(int? ist die gleiche wie Nullable<int>)

+0

Oder Sie könnten einfach 'Nullable.GetUnderlyingType()' – phoog

+0

Oder das aufrufen. In jedem Fall scheint es möglich, die für diese Frage erforderlichen Informationen zu erhalten. – keyboardP

+0

Das Problem ist, dass ich nicht weiß, ob das gegebene Objekt ein Nullable ist. Es könnte auch eine Zeichenfolge oder ein einfacher Int sein. Ich dachte, ich könnte den Typcheck verwenden, um diese Informationen zu erhalten. Aber das scheint nicht der Fall zu sein. –

0

Sie dies nicht tun können, noch sollten Sie wollen. Da Nullable<T> eine Struktur ist, haben value-type-Variablen dieses Typs alle Typinformationen, die Sie zum Zeitpunkt der Kompilierung benötigen. Verwenden Sie einfach den Operator typeof.

Auf der anderen Seite verfügen Sie möglicherweise über eine Nullable-Instanz, deren Typ Sie zur Kompilierungszeit nicht kennen.Das müsste eine Variable sein, deren statischer Typ object oder ein anderer Referenztyp ist. Howver, weil eine Nullable<T> Wert Boxen zu einem boxed T Wert, gibt es nicht so etwas wie eine boxed Nullable<T>. Diese Instanz, deren Typ Ihre Prüfung wird nur ein T sein.

Deshalb erhalten Sie das gleiche Ergebnis für is int und is Nullable<int>. Es gibt keine Möglichkeit, zwischen einer boxed int und einer boxed int?, zu unterscheiden, weil es keine boxed int? ist.

Siehe Nulls not missing anymore für weitere Einzelheiten.

0

Wie bereits darauf hingewiesen worden, null hat keinen Typ. Um herauszufinden, ob etwas int? vs long? ist, müssen Sie Reflektion verwenden, um Informationen über etwas zu erhalten, das den Typ speichert. Hier ist ein Code, den Sie als Inspiration nutzen kann in der Lage sein (nicht genau wissen, was Sie versuchen, den Code zu erreichen, ist ein bisschen komisch):

class Pair<T> where T : struct { 

    public Pair(T? a, T? b) { 
    A = a; 
    B = b; 
    } 

    public T? A { get; private set; } 

    public T? B { get; private set; } 

} 

void DoSomething<T>(Pair<T> pair) where T : struct { 
    DoMore(pair); 
} 

void DoMore(params object[] args) { 
    Console.WriteLine("Do more"); 
    var nullableIntPairs = args.Where(IsNullableIntPair); 
    foreach (Pair<int> pair in nullableIntPairs) { 
    Console.WriteLine(pair.A); 
    Console.WriteLine(pair.B); 
    } 
} 

bool IsNullableIntPair(object arg) { 
    var type = arg.GetType(); 
    return type.IsGenericType 
    && type.GetGenericTypeDefinition() == typeof(Pair<>) 
    && type.GetGenericArguments()[0] == typeof(int); 
} 

Wenn Sie führen Sie den folgenden Code

DoSomething(new Pair<int>(5, new int?())); 
DoSomething(new Pair<long>(new long?(), 6L)); 

Sie erhalten die folgende Ausgabe:

 
Do more 
5 
null 
Do more 
0

Sie können typeof verwenden:

a == typeof(Nullable<int>) //true 
a == typeof(int) //false 
Verwandte Themen