web-dev-qa-db-ja.com

Tがtype1またはtype2であるジェネリックメソッド

ジェネリック型がtype1 or type2であることをジェネリック関数を宣言する方法はありますか?

例:

public void Foo<T>(T number)
{
}

Tをintまたはlongに制約できますか

generic constraint を使用して各ジェネリック引数Tのタイプを制限することもできますが、残念なことに、Tがtype1 or type2であるかどうかをコンパイル時に適用できるものはありません。

また、総称引数がプリミティブ型(int、long、doubleなど)のみであることをコンパイル時に強制する方法もありません。

15
Darin Dimitrov

あなたができるReferenceTypeオブジェクトについて

public void DoIt<T>(T someParameter) where T : IMyType
{

}

...

public interface IMyType
{
}

public class Type1 : IMyType
{
}

public class Type2 : IMyType
{
}

あなたのケースでは、long asパラメータを使用すると、使用法がlongとintに制限されます。

public void DoIt(long someParameter)
{

}

任意の値タイプ(int、double、short、decimalなど)に制約するには、次のように使用できます。

public void DoIt<T>(T someParameter) where T : struct
{

}

詳細については、公式ドキュメントを確認してください ここ

16

番号。

それは意味がありません。 Tは、メソッドに使用可能なコンパイル時の型がありません。

代わりに、2つのオーバーロードメソッドを作成する必要があります。

8
SLaks

代わりにオーバーロードされたメソッドを使用してください:

public void Foo(int number)
{
} 

public void Foo(long number)
{
}

とにかくジェネリック型に対して算術演算を実行することはできません。 int値をlongパラメータに渡すことができることに注意してください。自動的にlongに変換されます。したがって、longパラメータを持つ単一のメソッドがあれば十分です。

古いプログラミング言語は、「1つしか存在できない」という原則に従って機能しました。 C#では、同じクラス、インターフェイス、または構造体に同じ名前の複数のメソッドを含めることができます。これらのメソッドには異なるシグネチャが必要です。つまり、異なる数のパラメーターまたは異なるタイプ(またはその両方)のパラメーターが必要です。これはメソッドのオーバーロードと呼ばれます。

私はこれが古い質問であることを知っており、これは完全に答えるものではありませんが、複数を作成したり、一般的な制約を使用したりするのではなく、単一の方法でこれを行うことができます...チェックする奇数型が20ある場合に特に便利です。

明らかに、制約を使用するときのようにコンパイラー・タイプ・チェックを取得しませんが、これは特定の状況で役立ちます...

public void MyMethod<T>()
{
    if (!typeof(T).Equals(typeof(int)) &&
        !typeof(T).Equals(typeof(long)))
            throw new Exception("T must be int or long");

    //your logic here
}
1
Detail

これは現在可能ではないと思います。

この質問 数学ライブラリの作成については、同じことをカバーしており、いくつかの回避策が含まれています。

0
Jon Egerton

私にもこの問題があり、より良い解決策を見つけたと思います(メソッドのオーバーロードされたバージョンでは不十分であると想定しています)。

既に記述されているように、Type1Type2をパラレルなしで混在させることは意味がありません。したがって、両方のオブジェクトタイプに対してアクセスするメソッドまたはプロパティが必要です。これらのメソッドまたはプロパティがオブジェクトで使用可能であることをコンパイラーに確認するには、インターフェースMyInterfaceを作成し、Type1およびType2で実装することにより、Type1およびType2をグループ化します。

interface MyInterface {
  void MyCommonMethod();
  bool MyCommonProperty { get; }
}

class Type1 : MyInterface {
  void MyCommonMethod() {
    // TODO: Implement it for Type1
  }

  bool MyCommonProperty {
  get {
    // TODO: Implement it for Type1
  }
  }
}

class Type2 : MyInterface {
  void MyCommonMethod() {
    // TODO: Implement it for Type2
  }

  bool MyCommonProperty {
  get {
    // TODO: Implement it for Type2
  }
  }
}

ここで、Fooメソッドを書き直してType1Type2の両方を受け入れるようにして、制約TMyInterfaceオブジェクトに変更します。

public void Foo<T>(T number) where T : MyInterface
{
  throw new NotImplementedException();
}

これは役に立つかもしれないと思います。 :)

0
KnorxThieus