如何å…许C#方法的泛型类型å‚数接å—nullå‚数?

时间:2011-04-10 14:43:02

标签: c# generics .net-4.0

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

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

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

å°è¯•ç§»æ¤æŸäº›Java代ç ï¼Œnull似乎是Tå‚æ•°çš„å¯æŽ¥å—值。


æ›´æ–°
谢谢:所有答案 - 特别是Eamonå’ŒJason。我ä¸å¸Œæœ›æ–¹æ³•è°ƒç”¨æ‰“扰类型推断。以下é‡è½½ä¿®å¤äº†å®ƒã€‚

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

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

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

应用相åŒçš„ä¿®å¤ç¨‹åº.. RFC 。 (忽略丑陋的扩展方法部分 - 这是å¦ä¸€ä¸ªé—®é¢˜ã€‚想è¦åœ¨æ²¡æœ‰ç»§æ‰¿çš„情况下在所有测试装置中使用这些方法。)

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

5 个答案:

答案 0 :(得分:11)

考虑以下方法:

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

是的,这是一ç§å¯é„™çš„愚蠢方法,使用泛型在这里毫无æ„义,但你马上就会明白这一点。

现在考虑

bool first = IsNullString<string>(null);
bool second = IsNullString<Foo>(null);

bool third = IsNullString(null);

在第一个和第二个中,编译器å¯ä»¥æ¸…楚地区分T的类型(ä¸éœ€è¦æŽ¨æ–­ï¼‰ã€‚第三,编译器如何推断T是什么?特别是,它无法区分T == stringå’ŒT == Foo,或任何其他类型。因此,编译器必须给你一个编译时错误。

如果你想解决这个问题,你需è¦æŠ•å°„null

EqualTo((object)null);

或明确说明类型

EqualTo<object>(null)

或定义é‡è½½

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

答案 1 :(得分:2)

如果没有明确指定T或进行强制转æ¢ï¼Œåˆ™æ— æ³•å®žçŽ°ã€‚泛型是编译时构造,因此如果编译器无法在编译时弄清楚类型,那么它将无法编译(正如您所看到的那样)。

答案 2 :(得分:2)

由于您无法完æˆæ‚¨æƒ³è¦åšçš„事情,如何定义EqualTo(object)é‡è½½æ–¹æ³•ï¼Ÿè¿™åº”该å…许您需è¦çš„语法。

答案 3 :(得分:2)

您å¯ä»¥ä½¿ç”¨ä»¥ä¸‹è¯­æ³•è§£å†³æ­¤é™åˆ¶ï¼š

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

default(T)是T类型字段的值,如果未设置。对于引用类型,它是null,对于值类型,它本质上是用零字节填充的内存(...对于ä¸åŒç±»åž‹å¯èƒ½æ„味ç€ä¸åŒçš„东西,但通常æ„味ç€æŸä¸ªç‰ˆæœ¬ä¸ºé›¶ï¼‰ã€‚

我现在å°è¯•é¿å…代ç ä¸­åˆ°å¤„都是null。它也阻ç¢äº†å…¶ä»–地方的类型推断,例如var声明字段和三元è¿ç®—符。例如,myArray==null ? default(int?) : myArray.Lengthå¯ä»¥ï¼Œä½†myArray==null ? null : myArray.Length将无法编译。

答案 4 :(得分:0)

也许实现一个éžæ³›åž‹çš„EqualTo,它将Object作为å‚数类型,å¯ä»¥è§£å†³é‡å†™è¿™äº›ä»£ç è¡Œçš„问题。