如何允许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 == string
和T == Foo
,或者任何其他类型。 因此,编译器必须给你一个编译时错误。
如果你想解决这个问题,你需要转换为null
EqualTo((object)null);
或明确说明类型
EqualTo
或定义过载
private static Matcher
如果没有明确指定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作为参数类型,可以解决重写这些代码行的问题。