6

したがって、ジェネリック型パラメーターを受け入れ、型パラメーターが特定の型のサブクラスである場合は少し特別な処理を行うクラスがあります。

IEnumerable<T> models = ...

// Special handling of MySpecialModel
if (filterString != null && typeof(MySpecialModel).IsAssignableFrom(typeof(T)))
{
    var filters = filterString.Split(...);
    models = 
        from m in models.Cast<MySpecialModel>()
        where (from t in m.Tags
               from f in filters 
               where t.IndexOf(f, StringComparison.CurrentCultureIgnoreCase) >= 0
               select t)
              .Any()
        select (T)m;
}

しかし、私は最後の行で例外を取得しています

Cannot convert type 'MySpecialModel' to 'T'

asキャストする代わりに使用するようにコードを変更すると、このエラーが発生します。

The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint.

ここで何が欠けていますか?

アップデート

このクラスのニーズは、structsや組み込み型を含む任意の型パラメーターを取ることができるため、私の場合、ジェネリック制約は適切な解決策ではありません。

4

6 に答える 6

3

次を試してください

select (T)(object)m;

T実行時に、それがのサブタイプであることを確認しましMySpecialModelたが、コンパイラはコンパイル時にこの情報にアクセスできません。関係のない2つのタイプ間で変換が試行されたことがわかります:TMySpecialModel

これを回避するにはobject、仲介者として使用する必要があります。MySpecialModelコンパイラは、への変換方法とへの変換方法を理解しobjectobjectTます。

于 2013-03-11T22:03:34.493 に答える
3

行うSelect(x => (MySpecialModel)x)

LINQCast<T>メソッドは、要素が既に存在する要素(基本型、派生型、インターフェイスなど)に要素をキャストする場合にのみ機能します。ターゲットタイプにキャストできるオブジェクトをキャストすることは意図されていません。(たとえばnew List<int>{1,2,3}.Cast<long>()、例外もスローします。

上記の答えは間違っていませんでしたが、それは質問に対処していません。

ジェネリックパラメーターが特定の型にバインドされていることをリフレクションで証明したからといって、コンパイラーがそれを認識しているわけではありません。これを機能させるには、Tインスタンスを共通の型(たとえばobject)にキャストしてから、特定の型にキャストする必要があります。例(クエリの最後の行をに変更すると、select (T)(object)mうまくいくはずです。

于 2013-03-11T21:50:03.783 に答える
1

最も簡単な修正は、キャストobject先の前に最初にキャストすることTです。

select (T)(object)m;

問題は、チェックが実行時に行われることですが、コンパイラはそれがステートメント内のTインスタンスでなければならないことを認識していません。したがって、安全ではない任意のタイプにキャストしようとしていることがわかり、エラーが発生します。MySpecialModelifTMySpecialModel

于 2013-03-11T22:03:00.470 に答える
1

ジェネリック型が常にクラスであることがわかっている場合は、クラスに型制約を追加できます。

public class Test<T> where T : class {}

それ以外の場合は、 smartcavemanが提案したように、オブジェクトを介してダブルキャストを実行します。

.Select(x => (T)(object)x); 
于 2013-03-11T21:53:40.983 に答える
0

asキーワードを使用するにはclass、汎用パラメーターに制約を設定します。

void MyMethod<T>(T item) where T : class
{
    //...
}
于 2013-03-11T21:52:30.517 に答える
0

制約を適用する場合があります。Nullable<T>これにより、キャストの可能性が有効になります(少なくとも「as」を使用)。

于 2013-03-11T22:01:00.513 に答える