3

実行時に変化する何かに関する情報を含む必要があるクラスが必要な状況があります。たとえば、次のようになります。

class Info<T>
{
    public T Max { get; set; }
    public T Min { get; set; }
    public T DefaultValue { get; set; }
    public T Step { get; set; }
    // Some other stuff
}

このクラスの多くのインスタンスを辞書に保存する必要がありますが、辞書を使用するには、たとえば 1 つの型を宣言する必要があるという問題があります。

Dictionary<string, Info<int>> dict = new Dictionary<string, Info<int>>();

この場合、別のタイプの情報を追加することはできませんInfo<double>。のようなものが欲しいのですが、以下のケースでは汎用バージョンを削除しました。

 {"Price", new Info{Min=100,Max=1000,DefaultValue=200,Step=50}}
 {"Adv", new Info{Min=10.50,Max=500.50,DefaultValue=20.50,Step=1.5}}
 {"Answer", new Info{Min=false,Max=false,DefaultValue=false,Step=false}}

使うことができますDictionary<string, Object> dict = new Dictionary<string, Object>();

しかし、dictアイテムを取得すると、それがどのタイプなのかわかりません。タイプも知る必要があります。たとえば、Priceそれは int で、 Adv は double です。実行時にどのように知ることができますか?

実際にバリデーターを作成したい (.Net Compact Framework 3.5 を使用している/組み込みシステムが存在する場合は使用できない) たとえば、以下のようなクラスがある場合..

class Demo
{
    public int Price { get; set; }
    public float Adv { get; set; }

    public static bool Validate(Demo d)
    {
        List<string> err = new List<string>();
        // here I have to get Info about the Price
        // from dictionary, it can be any storage
        Info priceInfo = GetPriceInfo("Price");
        if (d.Price < priceInfo.Min)
        {
            d.Price = priceInfo.Min;
            err.Add("price is lower than Min Price");
        }
        if (d.Price > priceInfo.Max)
        {
            d.Price = priceInfo.Max;
            err.Add("price is above than Max Price");
        }
        // need to do similar for all kinds of properties in the class  
    }
}

したがって、検証情報を1つの場所(辞書または別の場所)に保存し、検証時にその情報を使用することも考えられます.上記のシナリオをより良い方法で設計できるかどうかも知りたいですか?

これを行うためのより良い方法があるかもしれませんが、ガイドラインを教えてください。

4

4 に答える 4

4

非ジェネリック基本クラスを使用できます。

public abstract class Info {
}

public class Info<T> : Info {
}

現在、すべての異なるジェネリック型は同じ基本型から継承されているため、辞書でそれを使用できます。

Dictionary<string, Info> dict = new Dictionary<string, Info>();

インターフェイスがジェネリック型に依存しないプロパティとメソッドを基底クラスで定義し、それらをジェネリック クラスで実装できます。そうすれば、ジェネリック型を指定せずにそれらを使用できます。

タイプが必要なメソッドの場合、タイプごとに特定のコードが必要です。isandas演算子を使用して、型を確認できます。

Info<int> info = dict[name] as Info<int>;
if (info != null) {
  int max = info.Max;
}
于 2013-02-06T21:18:03.703 に答える
1

Microsoft から取得してIEnumerableインターフェイスを模倣し、.Cast<T>? dynamicただし、 (4.0+ のみ) またはリフレクションに入りたくない場合は、誰かがあなたのタイプについて知る必要があります。どちらもコストがかかります。たぶん、あなたのデザインを再考する必要がありますか?

于 2013-02-06T21:14:22.250 に答える
0

オブジェクトのディクショナリ(またはいくつかの基本クラス)を使用すると、データにアクセスするためのいくつかのオプションがあります(通常、操作する共通の基本クラスからのある種の継承を含み、以下に概説するプロパティがあります)。

  1. タイプを示すために列挙型を使用すると、ある種のスイッチ/ケースを持つことができます。(簡単ですが、C#ishではありません。)
  2. VARIANTに似たものを使用してください。バリアントは、格納する情報と格納される値の両方を提供する型であり、string、int、floatなどの任意の基本型にすることができます。(ここでの回答からわかるように、C#には実際には存在しません。C#のバリアント型。)
  3. また、実行時にオブジェクトのタイプをテストして、所有しているオブジェクトの種類を確認し、それをキャストして、そのタイプに応じてコンテンツを処理することもできます。(いくつかの方法..リフレクションを使用する必要があるかもしれません。最初はここを見てください:オブジェクトタイプを取得し、それに応じて値を割り当てます。)
  4. 実際には、各オブジェクトに対して実行する操作を何らかの方法で抽象化してから、その関数を呼び出すこともできます。コマンドパターンのようなもの。(コマンドパターン:パラメータをコマンドに渡す方法は?

おそらくもっとたくさん。:)

于 2013-02-06T21:50:15.027 に答える
0

Keith Nicholas の言うとおりです。ディクショナリで複数の型をサポートする場合は、インターフェイスが必要になりますが、それは一般的なものである必要があります。

次のようなことを試してください (警告: テストされていないコード):

interface IInfo<T>
{
    T Max { get; set; }
    T Min { get; set; }
    T DefaultValue { get; set; }
    T Step { get; set; }
}

Dictionary<string, IInfo> dict = new Dictionary<string, IInfo>();

class AnswerInfo : IInfo<bool> { }
class PriceInfo : IInfo<int> { }
class AdvInfo : IInfo<double> { }

dict["Answer"] = new AnswerInfo() { Min = false, Max = false, DefaultValue = false, Step = false };
dict["Price"] = new PriceInfo() { Min = 100, Max = 1000, DefaultValue = 200, Step = 50 };
dict["Adv"] = new AdvInfo() { Min = 10.50, Max = 500.50, DefaultValue = 20.50 Step = 1.5 };
于 2013-02-06T21:31:42.867 に答える