4

我有这个扩展方法:

public static bool In<T>(this T source, params T[] list)
{
    return list.Contains(source);
}

现在我需要将上述方法用于ushort. 当我尝试

ushort p = 3;
if (p.In(1, 2, 3, 4, 5))
   return;

第一行投到3一口井里ushort。但是当3作为参数传递时,我得到了错误

'ushort' 不包含 'In' 的定义,并且最佳扩展方法重载 'Extensions.In(T, params T[])' 有一些无效参数。

但这有效:

ushort p = 3;
if (Extensions.In(p, 1, 2, 3, 4, 5))
   return;

这很奇怪。

  1. 为什么它适用于第二个示例,而不适用于第一个示例?

  2. 有什么好的选择可以在这里帮助我?由于没有文字,short或者ushort我找不到比手动转换每个整数更简单的替代方法,如下所示:

    ushort p = 3;
    if (p.In((ushort)1, (ushort)2, (ushort)3, (ushort)4, (ushort)5))
       return;
    
4

2 回答 2

5

好吧,你定义了一个泛型函数,所以你必须定义它必须处理的确切类型。因为如果您只给函数提供数字(1234等)。它们可以是任何东西: short, ushort, integer...

所以你可以这样做:

或者

ushort p = 3;
if (p.In<ushort>(1, 2, 3, 4, 5))
   return;

或者就像您在第二个示例中所做的那样,将每个参数转换为所需的类型:

ushort p = 3;
if (p.In((ushort)1, (ushort)2, (ushort)3, (ushort)4, (ushort)5))
   return;

我个人更喜欢第一种情况。

编辑

为什么它在这种情况下有效:

ushort p = 3;
if (Extensions.In(p, 1, 2, 3, 4, 5))
   return;

是因为您像(第一个参数)一样显式传递编译器的已知类型,所以它可以推断它。thisp

默认1, 2, 3, 4, etc.类型是int。所以当你打电话

p.In(1, 2, 3, 4, 5)

T被视为(或倾向于)被视为integer价值。由于编译器不能保证不会丢失任何数据(当您使用ushort整数时),它会给出一条错误消息。它强制你显式定义一个更小的类型

请注意:函数参数的定义类似于T[],因此您传递整数(至少编译器是这样认为的)但假装它是ushort(当您从 调用 ext-method 时p)。

为了证明,尝试运行

int p = 3;
if (p.In(1, 2, 3, 4, 5))
   return;

这完美地工作。

于 2012-12-05T18:29:42.687 回答
1

为什么它适用于第二个示例,而不适用于第一个示例?

首先,让我们弄清楚编译器会推断出什么T。有些参数是ushort,有些是intushort有到 的隐式转换int并且int没有到 的隐式转换ushort,所以Tint

这里的关键在 C# 4 规范的第 7.6.5.2 节(强调我的):

如果满足以下条件,则扩展方法 Ci.Mj 是合格的:

  • Ci 是一个非泛型、非嵌套类
  • Mj 的名字是标识符
  • Mj 在作为静态方法应用于参数时是可访问和适用的,如上所示
  • 从 expr 到 Mj 的第一个参数的类型存在隐式标识、引用或装箱转换。

存在从to的隐式转换,但没有标识、引用或装箱转换! ushortint

因此,以下是合法的:

Extensions.In<ushort>(p, 1, 2, 3, 4, 5);
Extensions.In<int>(p, 1, 2, 3, 4, 5); // implicit conversion allowed
Extensions.In(p, 1, 2, 3, 4, 5); // T is int
p.In<ushort>(1, 2, 3, 4, 5);

但以下不是:

p.In<int>(1, 2, 3, 4, 5); // implicit conversion not allowed
p.In(1, 2, 3, 4, 5); // T is int

请注意,如果您定义In

public static bool In(this int source, params int[] list)
{
    return list.Contains(source);
}
于 2012-12-05T22:39:40.623 回答