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;

最初の行は井戸にキャスト3ushortます。しかし3、パラメータとして渡されると、エラーが発生します

'ushort' には 'In' の定義が含まれておらず、最適な拡張メソッド オーバーロード 'Extensions.In(T, params T[])' に無効な引数が含まれています。

しかし、これは機能します:

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

これは奇妙です。

  1. 2 番目の例では機能するのに、最初の例では機能しないのはなぜですか?

  2. ここで私を助ける良い代替手段は何ですか? のリテラルがないため、shortまたはushort次のように各整数を手動でキャストするよりも簡単な代替手段を見つけることができません。

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

2 に答える 2

5

さて、ジェネリック関数を定義するので、扱う必要がある正確な型を定義する必要があります。1関数に数字 ( 、234など) を与えるだけだからです。それらは何でもかまいません: short, ushort, integer...

したがって、次のことができます。

また

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

または、2 番目の例で行ったように、すべてのパラメーターを目的の型にキャストします。

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

2 番目の例では機能するのに、最初の例では機能しないのはなぜですか?

まず、コンパイラが何を推論Tするかを考えてみましょう。一部のパラメータはushortであり、一部はintです。 ushortには への暗黙的な変換があり、 への暗黙的な変換はありintませintん。 ushortTint

ここでの鍵は、C# 4 仕様のセクション 7.6.5.2 にあります (強調は私のものです)。

拡張メソッド Ci.Mj は、次の場合に適格です。

  • Ci は非ジェネリックでネストされていないクラスです
  • Mj の名前は識別子です
  • Mj は、上記のように静的メソッドとして引数に適用された場合にアクセス可能で適用可能です。
  • expr から Mj の最初のパラメーターの型への暗黙の同一性、参照、またはボックス変換が存在します。

からへの暗黙的な変換がありますが、 ID、参照、またはボックス化の変換はありません! 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 に答える