現在、フレームワークには、子孫が値型である可能性のある継承可能なクラスが3つだけあります:Object
、、、。これらの3つの型はすべてクラス型ですが、値型から派生した、または値型になり、派生していない型はクラス型になります。上記以外のタイプの場合、aまたは制約は冗長または矛盾します。偶然ではありませんが、C#では、上記のタイプに制約を直接指定することはできません。ValueType
Enum
ValueType
Enum
Object
ValueType
class
struct
一部の言語とフレームワークでは、一般的な設計哲学は、その一般的な形式に適用される動作が役に立たない特定の形式の表現がある場合、言語/フレームワークの設計者が禁止する理由がないというものです。そのような形。そのような哲学の下では、ジェネリック型を封印された型に制約することは完全に合法です(たとえば、問題の型が封印されていて、将来のバージョンがそうでないFnord)
場合、そのようなことは無意味です、しかし、ジェネリック制約の通常の解釈をそのような状況に適用すると、合理的な動作が得られ、そのような制約が役立つ可能性がある状況がある可能性があるため(たとえば、開発中で現在封印されているクラスを使用するコードを書くが、最終リリースで封印されている場合とされていない場合、または特定のジェネリック形式を期待するReflectionベースのコードとインターフェイスするコードを記述している場合、哲学は、ジェネリック型を封印されたクラスに制約することは合法であるべきだと示唆します。
他のいくつかの言語やフレームワークでは、異なる哲学が当てはまります。プログラマーが、ある特定の形式の構造が一般的な形式を超える機能を提供することを期待しているが、そうではない場合、およびその特定の形式がそのような機能なしではあまり役に立たないように思われる場合、言語の実装者がプログラマーがその実際の意味を表現したい理由を理解していない場合、構造が明確に定義され、他の手段で表現できない正確な意味を持っていても、言語はそれを禁止する必要があります。
C#も.netも、ある型パラメーターを別の型パラメーターに制約することに問題がないという事実は、他のパラメーターが制約として受け入れられないタイプである場合でも、制限が言語によって人為的に課されていることを示唆しています。前述の哲学。残念なことに、私見です。たとえば、言うことができると役立つ状況がたくさんあるからです。
bool HasAnyFlags<T>(this T enum1, T enum2) where T:struct,System.Enum
.netはそのような構成を有効に許可し、C#がそのような制約を除外することを妨げる唯一の障害は、それらを許可しないように明示的にそのような制約を探すことですが、C#の設計者は、そのような構成を許可するのではなく禁止することにしました。 .netがそれらを解釈するように動作します(つまり、でHasAnyFlags
できないことを直接行うT
ことはできません。また、 asSystem.Enum
を使用することは、通常、を使用するよりも速くはありませんが(場合によっては遅くなります)、いくつかの理由:T
System.Enum
System.Enum
T
- このメソッドは、コンパイル時に、パラメーターが*同じ*列挙型でなければならないことを強制できます。
- このメソッドは、静的クラス `EnumEvaluator`を使用して、タイプ` Func`の静的デリゲートを生成およびキャッシュし、 `HasAnyFlags(T enum1、T enum2)`を` return EnumEvaluator.HasAnyFlags(enum1、enum2);`として実装できます。 。このような関数は、`Enum.HasFlag`の10倍以上の速度になる可能性があります。
それでも、そのような制約を指定することは有用かもしれませんが、C#でそれらを指定する唯一の方法は、C#ソースコードに制約として使用できるダミータイプを指定させ、コンパイルされたコードをユーティリティを介して実行することです。ダミー型へのすべての参照を、最初に使用したい型への参照に置き換えます。