C# 可为null的类型检查<;int>;

C# 可为null的类型检查<;int>;,c#,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));

如果有以下方法:

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));
}
static void dosomething有两个可空值(可空a、可空b)
{
WriteLine(“参数a可为空:+(a可为空));
WriteLine(“参数a是int:+(a是int));
WriteLine(“参数b可为空:”+(b可为空));
WriteLine(“参数b是int:+(b是int));
}
当我以null作为参数调用此方法时,类型检查将为此参数返回false。例如,此代码

DoSomethingWithTwoNullables(5, new Nullable<int>());
doSomethingWithTwoNullable(5,newNullable());
此输出中的结果:

Param a is Nullable<int>: True
Param a is int          : True
Param b is Nullable<int>: False
Param b is int          : False
参数a可为空:True
参数a为int:True
参数b可为空:False
参数b为int:False

在使用可为null并传递null时,是否有任何方法可以保留类型信息?我知道在这个例子中检查类型是无用的,但它说明了问题所在。在我的项目中,我将参数传递给另一个方法,该方法采用
params object[]
数组并尝试识别对象的类型。此方法需要为
Nullable
Nullable

执行不同的操作。直接转到根本问题,不,您不能这样做。null
Nullable
与null
Nullable
具有完全相同的装箱表示,或者实际上是“正常”null。因为它的底层表示形式只是全零,所以无法判断null的“类型”。有关更多详细信息,请参阅。

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

从概念上讲,
新的可空

如果我们泛化一下,忘记了
Nullable


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

您可以尝试使用反射来实现这一点

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

int? myNullableInt = null;
Console.WriteLine(myNullableInt.GetValueOrDefault().GetType());
如果
myNullableInt
为空,将返回默认值。检查此返回值的类型,在这种情况下,它将返回
System.Int32
。您可以对返回的类型执行
If..else
/
开关
检查以执行相关操作


int?
Nullable
相同)

您不能这样做,也不应该这样做。由于
Nullable
是一个结构,因此这种类型的值类型变量具有编译时所需的所有类型信息。只需使用
typeof
操作符

另一方面,您可能有一个在编译时不知道其类型的可空实例。这必须是一个静态类型为
object
的变量或其他引用类型。然而,因为一个
Nullable
值与一个装箱的
T
值对应,所以不存在装箱的
Nullable
值。您将检查其类型为
T
的实例

这就是为什么对
is int
is Nullable
得到相同的结果。无法区分装箱的
int
和装箱的
int?
,因为没有装箱的
int?


有关详细信息,请参见。

正如前面指出的那样,
null
没有类型。要确定某个内容是否为
int?
vs
long?
,您需要使用反射来获取有关存储该类型的内容的信息。下面是一些代码,您可以将其作为灵感使用(不知道您试图实现什么代码有点奇怪):

类对,其中T:struct{
公共对(T?a,T?b){
A=A;
B=B;
}
公共T{get;私有集;}
公共T?B{get;私有集;}
}
void DoSomething(成对),其中T:struct{
多莫尔(对);
}
void DoMore(参数对象[]args){
Console.WriteLine(“多做”);
var nullableIntPairs=args.Where(IsNullableIntPair);
foreach(nullableIntPairs中的对){
控制台写入线(A对);
控制台写入线(B对);
}
}
bool IsNullableIntPair(对象参数){
var type=arg.GetType();
返回类型。IsGenericType
&&type.GetGenericTypeDefinition()==typeof(对)
&&type.GetGenericArguments()[0]==typeof(int);
}
如果执行以下代码

DoSomething(new Pair<int>(5, new int?()));
DoSomething(new Pair<long>(new long?(), 6L));
DoSomething(新的一对(5,新的int?());
DoSomething(新双(新长?(),6L));
您将获得以下输出:

Do more 5 null Do more 多做 5. 无效的 多做 您可以使用typeof:

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

因为b首先被装箱到
int?
导致一个空引用。大概您可以尝试{}catch{}来测试它,所以有一种方法可以找到答案。我打赌使用反射,你可以更进一步,并抛光它。也许初始化一个新实例,这应该给它一个默认值,然后执行
typeof(variable.value)
?@SLC:你不能。它只是一个没有类型信息的空引用。@SLC我从未见过比这更好的解释,来自微软的开发部门副总裁(我不记得他写这篇文章时的标题):实际上,没有底层表示,就像有
(string)null
(object)的底层表示一样空
。如果他做了
b=3?如果它是一个字符串,那么你会得到一个错误,但是如果它是一个int或可为null的int,你不会得到一个错误?你不能使用反射。对空引用调用
GetType()
将引发
NullReferenceException
。没有与空引用关联的类型。链接的文章基于类型,而不是对对象的引用(在本例中,对象可能为null)。或者您可以只调用
Nullable.GetUnderlyingTyp
Do more
5
null
Do more
a == typeof(Nullable<int>) //true
a == typeof(int) //false