简体   繁体   English

如何允许C#方法的通用类型参数接受空参数?

[英]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 == stringT == 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.

相关问题 如何在C#中重构方法以接受通用类型作为其参数? - How to refactor method to accept generic type as its argument in C#? C#泛型如何获取没有对象类型作为参数的泛型方法的参数类型? - C# Generics How Can I get the type passed as an argument for a generic method with no object type as a parameter? 如何在 C# 8 中允许可空泛型类型作为方法的返回类型? - How to allow nullable generic type in C# 8 as a return type for a method? 某种int的C#方法参数是否可以接受null并可以更新参数 - Is it possible that a C# method parameter of some kind of int can accept null and can update argument 如何使泛型方法允许返回null并接受枚举? - How to make a generic method allow returning null and accept enum? C#通用方法类型参数推断 - C# Generic method type argument inference 如何在c#中指定通用列表类型扩展方法的参数 - How to specify parameter for generic list type extension method in c# 在C#中检查泛型方法的类型参数 - Checking type parameter of a generic method in C# 如何约束通用类型参数以仅接受C#中的可为空的值类型? - How do I constraint a generic type parameter to only accept nullable value types in C#? 可以从表达式参数推断其类型参数的 C# 通用方法 - C# Generic method that can infer its type argument from expression parameter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM