简体   繁体   English

在Nullable上键入检查<int>

[英]Type checking on Nullable<int>

If have the following method: 如果有以下方法:

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

When i call this method with null as a parameter, the type check returns false for this parameter. 当我使用null作为参数调用此方法时,类型检查将为此参数返回false。 For example this code 例如这段代码

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

results in this output: 结果输出:

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

Is there any way to preserve the type information when using a Nullable and passing null? 有没有办法在使用Nullable并传递null时保留类型信息? I know that checking the type in this example is useless, but it illustrates the problem. 我知道在这个例子中检查类型是没用的,但它说明了问题。 In my project, I pass the parameters to another method that takes a params object[] array and tries to identify the type of the objects. 在我的项目中,我将参数传递给另一个采用params object[]数组的方法,并尝试识别对象的类型。 This method needs to do different things for Nullable<int> and Nullable<long> . 这个方法需要为Nullable<int>Nullable<long>做不同的事情。

Going straight to the underlying problem, no, you can't do this. 直接找到潜在的问题,不,你不能这样做。 A null Nullable<int> has exactly the same boxed representation as a null Nullable<long> , or indeed a 'normal' null. Nullable<int>具有完全相同的盒装表示作为一个空Nullable<long> ,或者确实是一个“正常”的空值。 There is no way to tell what 'type' of null it is, since its underlying representation is simply all-zeros. 没有办法告诉它是什么类型的null,因为它的底层表示只是全零。 See Boxing Nullable Types for more details. 有关详细信息,请参阅Boxing Nullable Types

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

If we generalise, forgetting about Nullable<T> : 如果我们概括,忘记Nullable<T>

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

we get false . 我们false false is the expected value for a type-check on a null value. false是对null值进行类型检查的预期值。

You can try using Reflection to achieve this. 您可以尝试使用Reflection来实现此目的。 Relevant article here. 相关文章在这里。

Unfortunately, null does not point to any specific memory location, and thus there is no metadata that you can associate with it to lookup the type. 不幸的是, null并不指向任何特定的内存位置,因此没有可以与之关联的元数据来查找类型。 Thus, you cannot gain any additional information about the variable. 因此,您无法获得有关变量的任何其他信息。

Unless I'm misunderstanding the question, you can get the type using GetType() . 除非我误解了这个问题,否则你可以使用GetType()来获取类型。 For example, 例如,

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

If myNullableInt is null, a default value will be returned. 如果myNullableInt为null,则返回默认值。 Check the type of this returned value and, in this case, it will return System.Int32 . 检查此返回值的类型,在这种情况下,它将返回System.Int32 You can do an If..else / Switch check on the returned type to perform the relevant action. 您可以对返回的类型执行If..else / Switch检查以执行相关操作。

( int? is the same as Nullable<int> ) int?Nullable<int>相同)

You can't do this, nor should you want to. 你不能这样做,你也不应该这样做。 Since Nullable<T> is a struct, value-type variables of this type have all the type information you need at compile time. 由于Nullable<T>是一个结构,因此这种类型的值类型变量具有编译时所需的所有类型信息。 Just use the typeof operator. 只需使用typeof运算符即可。

On the other hand, you might have a Nullable instance whose type you don't know at compile time. 另一方面,您可能有一个Nullable实例,其类型在编译时是您不知道的。 That would have to be a variable whose static type is object or some other reference type. 那必须是一个变量,其静态类型是object或其他一些引用类型。 Howver, because a Nullable<T> value boxes to a boxed T value, there's no such thing as a boxed Nullable<T> . 但是,因为Nullable<T>值框到盒装T值,所以没有盒装Nullable<T>这样的东西。 That instance whose type your checking will just be a T . 那个类型的实例,你的检查只是一个T

This is why you get the same result for is int and is Nullable<int> . 这就是为什么你得到与is int相同的结果并且is Nullable<int> There's no way to distinguish between a boxed int and a boxed int? 有没有办法区分盒装int和盒装int? , because there is no boxed int? ,因为没有盒装int? .

See Nulls not missing anymore for details. 有关详细信息,请参阅Nulls不再缺失

As it has already been pointed out null has no type. 正如已经指出的那样, null没有类型。 To figure out if something is int? 要弄清楚是否有东西int? vs long? vs long? you need to use reflection to get information about something storing the type. 你需要使用反射来获取有关存储类型的信息。 Here is some code that you may be able to use as inspiration (not knowing exactly what you try to achieve the code is a bit weird): 下面是一些代码,您可以将它们用作灵感(不知道您尝试实现代码的确切内容有点奇怪):

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

If you execute the following code 如果您执行以下代码

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

you get the following output: 你得到以下输出:

Do more
5
null
Do more

You can use typeof : 你可以使用typeof:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM