在Nullable <int> </int>上键入检查

时间:2012-10-15 13:54:36

标签: c#

如果有以下方法:

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));
}

当我使用null作为参数调用此方法时,类型检查将为此参数返回false。例如这段代码

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

导致此输出:

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

使用Nullable并传递null时,有没有办法保留类型信息?我知道在这个例子中检查类型是没用的,但它说明了问题。在我的项目中,我将参数传递给另一个采用params object[]数组的方法,并尝试识别对象的类型。此方法需要对Nullable<int>Nullable<long>执行不同的操作。

8 个答案:

答案 0 :(得分:5)

直接找到根本问题,不,你不能这样做。 null Nullable<int>具有与null Nullable<long>完全相同的盒装表示,或者实际上是'normal'null。没有办法告诉它是什么类型的null,因为它的底层表示只是全零。有关详细信息,请参阅Boxing Nullable Types

答案 1 :(得分:3)

从概念上讲,new Nullable<int> null

如果我们概括,忘记Nullable<T>

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

我们得到falsefalse是对null值进行类型检查的预期值。

答案 2 :(得分:1)

您可以尝试使用Reflection来实现此目的。 Relevant article here.

答案 3 :(得分:0)

不幸的是,null没有指向任何特定的内存位置,因此没有可以与之关联的元数据来查找类型。因此,您无法获得有关变量的任何其他信息。

答案 4 :(得分:0)

除非我误解了这个问题,否则您可以使用GetType()获取该类型。例如,

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

如果myNullableInt为null,则返回默认值。检查此返回值的类型,在这种情况下,它将返回System.Int32。您可以对返回的类型进行If..else / Switch检查以执行相关操作。

int?Nullable<int>

相同

答案 5 :(得分:0)

你不能这样做,你也不想这样做。由于Nullable<T>是结构,因此此类型的值类型变量具有编译时所需的所有类型信息。只需使用typeof运算符。

另一方面,您可能有一个Nullable实例,其类型在编译时是您不知道的。那必须是一个静态类型为object或其他引用类型的变量。不管怎么说,因为Nullable<T>值框装入了T盒装值,所以没有装箱Nullable<T>这样的东西。那个类型只需要检查的实例T

这就是为is intis Nullable<int>获得相同结果的原因。由于没有装箱int,因此无法区分盒装int?和盒装int?

有关详细信息,请参阅Nulls not missing anymore

答案 6 :(得分:0)

正如已经指出null没有类型。要确定某些内容是int?还是long?,您需要使用反射来获取有关存储该类型的内容的信息。下面是一些代码,您可以将它们用作灵感(不知道您尝试实现代码的确切内容有点奇怪):

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);
}

如果执行以下代码

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

你得到以下输出:

Do more
5
null
Do more

答案 7 :(得分:0)

您可以使用typeof:

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