如何允许C#方法的generics类型参数接受null参数?

private static Matcher EqualTo(T item) { return new IsEqual(item); } 

如何修改上述方法定义,以使以下内容有效/允许。

 EqualTo("abc"); EqualTo(4); EqualTo(null); // doesn't compile. EqualTo(null) does 

尝试移植一些Java代码,其中null似乎是T参数的可接受值。


更新
谢谢:所有答案 – 尤其是Eamon和Jason。 我不希望方法调用打扰类型推断。 以下过载修复了它。

  private static Matcher EqualTo(object item) { return EqualTo(item); } 

实际上,上述问题是一个更大难题的一部分。 最终目标是让以下工作。

  this.AssertThat(null, EqualTo(null)); this.AssertThat(null, Not(EqualTo("hi"))); this.AssertThat("hi", Not(EqualTo(null))); 

应用相同的修复.. RFC 。 (忽略丑陋的扩展方法部分 – 这是另一个问题。想要在没有inheritance的情况下在所有测试装置中使用这些方法。)

 public static void AssertThat(this object testFixture, object actual, Matcher matcher, string message = "") { AssertThat(anyObject, (T)actual, matcher, message); } public static void AssertThat(this object testFixture, T actual, Matcher matcher, string message = "") where T : TSuper { ... check and assert 

考虑以下方法:

 public bool IsNullString(T item) { return typeof(T) == typeof(string) && item == null; } 

是的,这是一种可鄙的愚蠢方法,使用generics在这里毫无意义,但你会在一瞬间看到这一点。

现在考虑

 bool first = IsNullString(null); bool second = IsNullString(null); bool third = IsNullString(null); 

在第一个和第二个中,编译器可以清楚地区分T的类型(不需要推断)。 第三,编译器如何推断出T是什么? 特别是,它无法区分T == stringT == Foo ,或者任何其他类型。 因此,编译器必须给你一个编译时错误。

如果你想解决这个问题,你需要转换为null

 EqualTo((object)null); 

或明确说明类型

 EqualTo(null) 

或定义过载

 private static Matcher EqualTo(object item) { return new IsEqual(item); } 

如果没有明确指定T或进行强制转换,则无法实现。 generics是编译时构造,因此如果编译器无法在编译时弄清楚类型,那么它将无法编译(如您所见)。

既然你不能完全做你想做的事情,那么如何定义一个EqualTo(object)重载方法呢? 这应该允许您所需的语法。

您可以使用以下语法解决此限制:

 EqualTo("abc"); EqualTo(4); EqualTo(default(object)); //equivalently: EqualTo((object)null); 

default(T)default(T)类型字段未设置的值。 对于引用类型,它为null ,对于值类型,它本质上是用零字节填充的内存(…对于不同类型可能意味着不同的东西,但通常意味着某些版本为零)。

我现在试着在我的代码中到处避免使用null 。 它也妨碍了其他地方的类型推断,例如var声明字段和三元运算符。 例如, myArray==null ? default(int?) : myArray.Length myArray==null ? default(int?) : myArray.Length ,但myArray==null ? null : myArray.Length myArray==null ? null : myArray.Length不会编译。

也许实现一个非generics的EqualTo,它将Object作为参数类型,可以解决重写这些代码行的问题。