[英]How to allow a generic type parameter for a C# method to accept a null argument?
private static Matcher<T> EqualTo<T>(T item)
{
return new IsEqual<T>(item);
}
How do I modify the above method definition such that the following are valid/allowed. 如何修改上面的方法定义,以使以下内容有效/允许。
EqualTo("abc");
EqualTo(4);
EqualTo(null); // doesn't compile. EqualTo<string>(null) does
Trying to port some Java code where null
seems to be acceptable value for a T
parameter. 尝试移植一些Java代码,其中
T
参数的null
似乎是可接受的值。
Update 更新资料
Thanks: for all the answers - especially Eamon and Jason. 谢谢:所有的答案-特别是Eamon和Jason。 I didn't want the method calls to bother with type-inference.
我不想让方法调用烦扰类型推断。 The following overload fixed it.
以下过载对其进行了修复。
private static Matcher<object> EqualTo(object item)
{
return EqualTo<object>(item);
}
Actually the above question was a part of a larger puzzle. 实际上,上述问题是一个更大难题的一部分。 The end goal was for the following to work.
最终目标是使以下工作正常进行。
this.AssertThat(null, EqualTo(null));
this.AssertThat(null, Not(EqualTo("hi")));
this.AssertThat("hi", Not(EqualTo(null)));
Applied the same fix.. RFC . 应用了相同的修补程序。RFC 。 (Ignore the ugly extension method part - that's another problem. Wanted to have these methods in all test-fixtures without inheritance.)
(忽略丑陋的扩展方法部分-这是另一个问题。想要在所有测试夹具中都使用这些方法而无需继承。)
public static void AssertThat<T>(this object testFixture, object actual, Matcher<T> matcher, string message = "")
{
AssertThat(anyObject, (T)actual, matcher, message);
}
public static void AssertThat<T, TSuper>(this object testFixture, T actual, Matcher<TSuper> matcher, string message = "") where T : TSuper
{
... check and assert
Consider the following method: 请考虑以下方法:
public bool IsNullString<T>(T item) {
return typeof(T) == typeof(string) && item == null;
}
Yes, this is a pathetically stupid method and using generics is pointless here, but you'll see the point in a moment. 是的,这是一个可悲的愚蠢方法,在这里使用泛型是没有意义的,但是稍后您会明白这一点。
Now consider 现在考虑
bool first = IsNullString<string>(null);
bool second = IsNullString<Foo>(null);
bool third = IsNullString(null);
In the first and second, the compiler can clearly distinguish the type of T
(no inference is needed). 在第一个和第二个中,编译器可以清楚地区分
T
的类型(无需推断)。 In the third, how the compiler infer what T
is? 第三,编译器如何推断
T
是什么? In particular, it can't distinguish between T == string
and T == Foo
, or any other type for that matter. 特别是,它无法区分
T == string
和T == Foo
,或其他任何类型。 Therefore, the compiler has to give you a compile-time error. 因此,编译器必须给您一个编译时错误。
If you want to get around this, you either need to cast null
如果您想解决这个问题,则需要强制为
null
EqualTo((object)null);
or explicitly state the type 或明确说明类型
EqualTo<object>(null)
or define an overload 或定义重载
private static Matcher<object> EqualTo(object item) {
return new IsEqual<object>(item);
}
Not possible without explicitly specifying a T or doing a cast. 如果没有明确指定T或进行强制转换,则无法实现。 Generics are compile time constructs and as such if the compiler can't figure out the type at compile time, then it won't compile (as you're seeing).
泛型是编译时的构造,因此,如果编译器无法在编译时弄清类型,那么它将无法编译(如您所见)。
Since you can't do exactly what you are wanting to do, how about defining an EqualTo(object)
overloaded method? 由于您无法完全执行您想做的事情,如何定义一个
EqualTo(object)
重载方法? That should allow your required syntax. 那应该允许您需要的语法。
You may work around this limitation by using the following syntax: 您可以使用以下语法解决此限制:
EqualTo("abc");
EqualTo(4);
EqualTo(default(object));
//equivalently:
EqualTo((object)null);
default(T)
is the value a field of type T
has if not set. 如果未设置,则
default(T)
是类型T
的字段具有的值。 For reference types, it's null
, for value types it's essentially memory filled with zero bytes (...which may mean different things for different types, but generally means some version of zero). 对于引用类型,它为
null
;对于值类型,它本质上是零字节填充的内存(...这可能意味着不同类型的事物不同,但通常意味着某种形式的零)。
I try to avoid the null
everywhere in my code nowadays. 如今,我尝试在代码中的所有位置避免使用
null
。 It hampers type inference elsewhere too, such as with the var
declared field and in a ternary operator. 它也会阻碍其他地方的类型推断,例如使用
var
声明字段和三元运算符。 For example, myArray==null ? default(int?) : myArray.Length
例如,
myArray==null ? default(int?) : myArray.Length
myArray==null ? default(int?) : myArray.Length
is OK, but myArray==null ? null : myArray.Length
myArray==null ? default(int?) : myArray.Length
可以,但是myArray==null ? null : myArray.Length
myArray==null ? null : myArray.Length
won't compile. myArray==null ? null : myArray.Length
无法编译。
也许实现一个以对象为参数类型的非泛型EqualTo可以解决重写这些代码行的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.