5

ジェネリッククラスを作成しようとしています:

public class ClassName<T>
{
    public T AccessEntity(string id)
    {
        return (from e in ServiceContext.CreateQuery<T>(TableName)
                where e.RowKey == id // error here!
                select e).FirstOrDefault();
    }
}

このコードでは、次のエラーが発生しています。

T には RowKey の定義が含まれていません

ただし、実行時に T を置き換えるパラメーターには、RowKey の定義があります。おそらく、コンパイル時にコンパイラが T の RowKey の定義を取得していないため、このエラーが発生しています。誰でもこの問題を解決する方法を教えてもらえますか?

4

5 に答える 5

11

これを行うには、インターフェイスの制約が必要になります。

interface IHazRowKey {
     string RowKey { get; } 
}

そして、次の制限を指定します。

public class classname<T> where T : IHazRowKey {...}

そして: IHazRowKey、実装ごとに次のように指定します。

public class Foo : IHazRowKey {....}

既存のRowKeyメンバーはそれに一致する必要があるため (フィールドではなくプロパティであると仮定)、他の余分なコードを追加する必要はありません。それが実際にフィールドである場合(IMOであってはなりません)、次のようになります。

public class Foo : IHazRowKey {
    string HazRowKey.RowKey { get { return this.RowKey; } }
    ...
}
于 2012-07-23T14:50:23.397 に答える
8

C++ テンプレートと C# ジェネリックには大きな違いがあります。ジェネリックをインスタンス化するために渡すクラスは問題ではありませんT。ジェネリック クラスまたはメソッドのコンパイル時にコンパイラがメソッドを認識していない場合は、エラー。これは、C# がインスタンス化の場所とは別にジェネリック コードをコンパイルする機能を必要とするためです (C# にはヘッダーがないことに注意してください)。

Tジェネリック内でプロパティとメソッドを使用するために、インターフェイスを定義し、それに制限することができます。RowKeyインターフェイスに追加しwhere T : myinterface、ジェネリック宣言に追加します。

于 2012-07-23T14:50:14.410 に答える
3

これを解決するには、制約を定義する必要があります。

public interface IHasRowKey
{
   string RowKey {get;}
}

public class classname<T> where T : IHasRowKey
{

}
于 2012-07-23T14:49:43.827 に答える
1
class YourClass // or extract an interface
{
    public string RowKey { get; set; }
}

class YourGeneric<T> where T : YourClass
{
    // now T is strongly-typed class containing the property requested
}
于 2012-07-23T14:49:07.943 に答える
0

私の場合、インターフェースを使用して RowKey を含めることはできません。これは、異なるプロパティとメソッドを持つ 2 つのクラスがあるためです。それらをマージして、これらのプロパティとメソッドを1つのラッパーインターフェイスまたはクラスに入れることはできません。ジェネリッククラスを使用する目的が失われるためです。私の解決策は、ジェネリック クラスでリフレクションを使用することです。例えば:

public class ClassName<T> {
    private T _genericType;
    public ClassName(T t) {
        _genericType = t;
    }

    public void UseGenericType() {
        // Code below allows you to get RowKey property from your generic 
        // class type param T, cause you can't directly call _genericType.RowKey
        PropertyInfo rowKeyProp = _genericType.GetType().GetProperty("RowKey");
        if(rowKeyProp != null) { // if T has RowKey property, my case different T has different properties and methods
            string rowKey = rowKeyProp.GetValue(_genericType).ToString();
            // Set RowKey property to new value
            rowKeyProp.setValue(_genericType, "new row key");
        }
    }
}

PropertyInfo クラスへの参照は次のとおりですhttp://msdn.microsoft.com/en-us/library/System.Reflection.PropertyInfo_methods(v=vs.110).aspx

于 2014-09-25T01:56:09.827 に答える