1

私はこのようなクラスを持っています:

public class ItemField
{

    public string FieldName { get; set; }

    public object FieldValue
    {
        get;
        set;
    }
}

「FieldValue」が文字列型、MyItem型、またはList<MyItem>型のみになるようにしたいと思います。また、コードがこのクラスを消費するときに、「FieldValue」にアクセスすると正しいタイプのオブジェクトが返されるようにする必要があります。これを行う方法はありますか?ジェネリックについてはあまり明確ではありませんが、それを使用してこれを行う方法があるようです...

4

5 に答える 5

2

プロパティは1つの特定の型のみを返すことができ、フィールド値の実際の型に応じて異なるデータ型を返すようにすることはできません。

クラスにジェネリックスを使用できますが、そのクラスに格納するデータのタイプのクラスインスタンスを作成する必要があります。

public class ItemField<T> {

  public string FieldName { get; set; }

  public T FieldValue {
    get;
    set;
  }

}
于 2012-09-20T19:38:31.123 に答える
2

クライアントが取得するフィールドのタイプを正確に知っていると仮定すると、プロパティ定義を次のようにジェネリックを使用する関数に変更できます。

private object fieldValue;

public T GetFieldValue<T>() {
    return (T)fieldValue;
}

ユーザーは次のようにこのメソッドを呼び出す必要があります。

MyItem item = itemField.GetFieldValue<MyItem>();

ただし、キャストはまだ存在しており、ジェネリック型パラメーターとして提供する型をユーザーがどのように知っているかは明確ではありません。

より良いアプローチは、ある種のダブルディスパッチメカニズム、たとえばビジターパターンを使用して、方向を「反転」し、フィールドに値を呼び出し元に「プッシュ」させることです。

interface IItemFieldVisitor {
    void VisitString(string val);
    void VisitMyItem(MyItem val);
    void VisitList(IList<MyItem> val);
}

interface IItemField {
    string Name {get;set;}
    void Accept(IItemFieldVisitor visitor);
}

class StringItemField : IItemField {
    public string Name {get;set;}
    private string val;
    public void Accept(IItemFieldVisitor visitor) {
        visitor.VisitString(val);
    }
}

class MyItemItemField : IItemField {
    public string Name {get;set;}
    private MyItem val;
    public void Accept(IItemFieldVisitor visitor) {
        visitor.VisitMyItem(val);
    }
}

class MyItemListItemField : IItemField {
    public string Name {get;set;}
    private IList<MyItem> val;
    public void Accept(IItemFieldVisitor visitor) {
        visitor.VisitList(val);
    }
}

これで、インターフェイスのインスタンスを作成し、それらをオブジェクトIItemFieldVisitorに渡すことができます。訪問者は、訪問されているオブジェクトIItemFieldのタイプを知らなくても、特定の値を持つコールバックを受け取ります。IItemField

于 2012-09-20T19:38:52.720 に答える
1

独自の抽象クラス「Field」を作成し、文字列、MyItem、またはListを抽象クラスから派生させることができます。http://www.techotopia.com/index.php/Understanding_C_Sharp_Abstract_Classes

次のリンクで抽象クラスファクトリを調べることができます:http: //dotnetslackers.com/articles/designpatterns/Design-Patterns-Part-3.aspx

于 2012-09-20T19:43:48.390 に答える
1

そのため、1つのアイテムを返品するのか、アイテムのコレクションを返品するのかがわからないようです。戻り値のタイプを動的に変更する(これは実際には便利な方法ではできないことです)よりも、常にコレクションを返す方が理にかなっています。そのコレクションには、適切な場合は常に1つのアイテムを含めることができます。

リターンタイプをに変更するとList<MyItem>、ほとんどの問題と悪いコードの臭いが消えます。

于 2012-09-20T19:59:58.493 に答える
1

string一般的な制約として使用されていないことをご存知のとおり、 MSDNをご覧ください。

public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>

したがって、Tを文字列として制約する場合は、このように回避できます。

public class ItemField<T> where T :  ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
{
    public string FieldName { get; set; }
    public T FieldValue { get; set; }

}
于 2012-09-21T07:10:14.163 に答える