25

可能な重複:

誰もが列挙型ジェネリック制約の欠如に対する良い解決策を知っていますか?

Tを列挙型に束縛する汎用メソッドを作成する

ジェネリック型のパラメータ[私はそれが正しいかどうかわかりません]をEnum

たとえば、このようなことをするにはどうすればよいですか?

//VB.NET
Function GetValues(Of T As System.Enum)(ByVal value As T) As IEnumerable(Of T)
    Return [Enum].GetValues(value.GetType)
End Function

//C#
public IEnumerable<T> GetValues<T>(T value) where T : System.Enum
{
    return Enum.GetValues(value.GetType());
}

更新

私は最終的にJon Skeetの制約のないメロディその目的のために。あなたの貢献に感謝します。


4 답변


7

残念ながら、あなたはできません - マイクロソフトでは、この問題を修正しないアイテムとしてクローズしました

列挙型を構造体として扱い、代わりに制約として使用することができます(Jon Skeetが制約のないメロディ?)それは見苦しいものです。


  • Jon SkeetのUnconstrained Melodyを指摘してくれてありがとう。とても役に立ちました。 - Alex Essilfie
  • リンクが壊れています。 - AbleArcher
  • C#7.3では実際に列挙型によるジェネリック制約を制約する機能が追加されました。ソース - Tyler Gill

16

あなたはできません。代わりの解決法は、structランタイムチェックを実行します。

public IEnumerable<T> GetValues<T>(T value) where T : struct
{  
    if (!typeof(T).IsEnum) throw new NotSupportedException();
    return (IEnumerable<T>)Enum.GetValues(value.GetType()); 
} 


  • コンパイルさえすれば、これは望みの結果を返しません。Enum.GetValues返すArray(その要素は単にオブジェクトです)、暗黙的にIEnumerable<T>。 - KeithS
  • 残念ながら、あなたのソリューションは一般的な列挙可能なリストを返しません。それは私にいくつかの洞察を提供した。ありがとう。 - Alex Essilfie
  • 私はあなたのソリューションを実装しました。@キース&#39;関連性があるが、異なる目的のために。 - Alex Essilfie

5

マットとダニーの答えはどちらも答えが半分です。これは実際に必要なものを手に入れます:

public IEnumerable<T> GetValues<T>() where T : struct
{   
    if (!typeof(T).IsEnum) throw new InvalidOperationException("Generic type argument is not a System.Enum");
    return Enum.GetValues(typeof(T)).OfType<T>(); 
} 

ダニーの答えからの変更点:

  • ジェネリック型のパラメータを持つと型の推論が可能になりますが、実際には使用されていないので、(パラメータを取らないLinqメソッドのように)ジェネリック型を明示的に指定する方が適切です。
  • Enum.GetValues()はObjectの配列を返します。これは暗黙のうちにTのIEnumerableにキャストされません。結果をキャストする余分なLinqメソッド(技術的にはOfTypeはフィルタ演算ですが、この場合はすべてを返します)は戻り値の型に従います。
  • オプション:NotSupportedExceptionはスローする例外の選択肢と同じくらい良い選択肢ですが、他にもオプションがあります。 ArgumentException、InvalidOperationException、InvalidCastExceptionなどがあります。InvalidOperationExceptionが選択されています。非enum型からenum値を取得しようとする無効な試み。これは意味論的なものであり、私は誰の論理とも議論するつもりはない。


  • キャストメソッドを使用するだけではどうですか?return Enum.GetValues(typeof(T)).Cast<T>() - Metro Smurf
  • このケースではおそらくうまくいくでしょうが、ユーザーが期待するように動作しない場合には、このサイトにいくつか質問があります。私はOfTypeまたはSelectのほうを避けて、明確な方法で仕事をすることを好む。 - KeithS
  • 私はあなたのソリューションを実装しました。@ダニーチェン関連性があるが、異なる目的のために。 - Alex Essilfie

2

この方法で汎用メソッドを汎用化する必要はありません。

あなたはSystem.Enumあなたの戻り値の型の型パラメータとして:

using System.Linq;
.
.
.
public IEnumerable<Enum> GetValues(Enum value)
{
    return Enum.GetValues(value.GetType()).OfType<Enum>();
}


  • 残念ながら、これは渡された列挙型に強く型付けされていません。 System.Enumsを含むリストを取得し、適切な型にキャストしなければなりません。 - KeithS
  • @KeithS:Danny Chenの答えとOPのオリジナルコード(実際にはうまくいかないArray一般的なものではありません)。 - Matt Ellen
  • いいえ。ジェネリックは、その特定の列挙型の値の強く型付けされたリストを返します。戻り値の型のキャストは必要ありません(数字や文字列などが必要な場合を除きます)。しかし、彼は他の理由でも働かない。 - KeithS

リンクされた質問


関連する質問

最近の質問