在C#中,如何测试一个变量是否为值类型?

4

我有几个地方使用了不受类 (或结构体) 限制的泛型类型参数,当我试图将该类型的变量与 null 进行比较时,Resharper 会将其下划线标记,并抱怨我可能正在将值类型与 null 进行比较(这确实是一个有效的反对意见)。是否有一种被接受的方法可以在比较之前检查变量是否为值类型?

例如:

public TObject MyProperty { get; set; }

...
private void SomeMethod()
{
    if(MyProperty == null) //Warning here
    {
       ...
    }
}

我一直在使用if(!(MyProperty is ValueType) && MyProperty),这个语句是否有效?它并没有消除警告,但这并不一定意味着什么。


1
顺便说一句,"C#.NET" 这个东西并不存在。这门语言的名字是 "C#"。 - John Saunders
2
如果你最终“想要”将值类型与null进行比较,那么你可能存在更深层次的问题。 - H H
在这种情况下,您不需要进行检查 - 如果MyProperty是值类型,则相等性将返回false。编译器将编写代码首先将MyProperty转换为Nullable <TObject>。尽管如此,警告仍然有效,因为它表明您的输入有些松散。 - James Gaunt
如果您事先知道类型是否可以为null,则无需进行测试。如果您的方法是通用的,则不会生成警告。因此,测试也是不必要的。最后,还有可空值类型。 - CodesInChaos
@Henk Holterman 真的吗?那么你会如何处理这样的情况:一个查询构建器,它接受一个通用类型,可以是任何类型--引用或值--和一个 SQL 转换方法,该方法需要输出 BETWEEN 子句,但如果 BETWEEN 子句的任一操作数为 null,则会抛出异常。是的,您可以使用 object 代替类型参数,但如果您想将操作数限制为相同类型怎么办?基本上,我认为在不知道变量是值类型还是引用类型时,比较变量与 null 的确有有效的用例。 - Turner Hayes
4个回答

7

如果是值类型,你想做什么?有时我会这样做:

public void DoStuff<T> (T variable)
{
    if(variable == default(T))
        ...  // true if null or 0 in the case of a value type
}

或者:

if( typeof(T).IsValueType )

在这里查看此处


我喜欢使用 default(T) 的方式来实现它。 - Rex Morgan
如果对象是值类型,我希望比较返回false(基本上,这些情况下,如果对象是引用类型且为null,我想执行一些特定的逻辑,但代码的其余部分并不关心)。听起来编译器已经会处理这个问题了——我不确定它如何处理这种情况。 - Turner Hayes
@CodingWithSpike 我没有对这两个解决方案进行基准测试,但哪一个会更快,为什么呢? - Natalie Perret

2

您可以使用反射,但它速度较慢,应该避免使用:

bool isValueType = typeof(TObject).IsValueType;

你的通用方法是否真的需要将引用类型和值类型作为其类型参数传递?


你有一个小的“笔误” :) - leppie
我认为应该是 typeof(TObject) 或者 MyProperty.GetType() - stakx - no longer contributing
@leppie:修复了,谢谢,你们两个都是对的。 - BrokenGlass

1

你可以直接比较类型:

if (MyProperty.GetType() == typeof(...))
{

}

你收到了一个警告,因为MyProperty没有被赋值。


1
如果MyProperty为空,MyProperty.GetType()会抛出一个NullReferenceException异常。 - David Yaw

0
public static bool IsNull<T>(T t)
{
    return ((Object)t == null);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接