5

如果有以下方法:

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>

4

8 回答 8

5

直奔根本问题,不,你不能这样做。nullNullable<int>具有与 null 完全相同的盒装表示Nullable<long>,或者实际上是“正常”null。没有办法知道它是什么类型的 null,因为它的底层表示只是全零。有关更多详细信息,请参阅装箱可空类型

于 2012-10-15T13:57:39.963 回答
3

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

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

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

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

于 2012-10-15T13:59:54.010 回答
1

您可以尝试使用反射来实现这一点。相关文章在这里。

于 2012-10-15T14:01:05.313 回答
0

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

于 2012-10-15T13:58:33.437 回答
0

除非我误解了这个问题,否则您可以使用GetType(). 例如,

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

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

int?与 相同Nullable<int>

于 2012-10-15T14:16:50.020 回答
0

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

另一方面,您可能有一个 Nullable 实例,您在编译时不知道其类型。那必须是一个静态类型为object或其他引用类型的变量。但是,因为一个Nullable<T>值框到一个装箱T值,所以没有装箱之类的东西Nullable<T> 您检查的类型将只是一个T.

这就是为什么 和 得到相同结果的is int原因is Nullable<int>。没有办法区分 boxedint和 boxed int?,因为没有 boxed int?

有关详细信息,请参阅Null 不再丢失

于 2012-10-15T14:21:36.203 回答
0

正如已经指出的,null没有类型。要确定某事是否是int?vs 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));

你得到以下输出:

多做
5
空值
多做
于 2012-10-15T14:23:30.907 回答
0

您可以使用 typeof :

a == typeof(Nullable<int>) //true
a == typeof(int) //false
于 2013-08-27T09:11:21.953 回答