6

まず、私の質問のかなり面白い名前を許してください。私はネイティブ スピーカーではありませんが、これらの数文字で自分の考えを表現するのに 10 分かかりました。

私がやろうとしているのは、C# で辞書を作成して、値を an int、 astringまたは aのいずれかにできるようにすることboolです。最初に頭に浮かんだのはジェネリックを使用することでしたが、私の知る限り、可能な値型として定義できる型は 1 つだけであり、「それらの 1 つになる」ことはできません。を使用objectすることも可能ですが、ボクシングはかなりのパフォーマンスキラーのようです。

これを行う方法はありますか?

これが私の頭に浮かんだことの例です:

Dictionary<string, (string, int, bool)> foo = new Dictionary<string, (string, int, bool)>();
foo.Add("key1", "Hello, World!"); //Correct - Value is a string
foo.Add("key2", 37); //Correct - Value is an int
foo.Add("key3", true); //Correct - Value is a boolean
foo.Add("key4", new Foobar()); //Compiler error - Value is a Foobar

私の最終的な目標は、他の開発者にライブラリを提供することです。この機能により、実行時に「変数」を定義し、型を与えることができるようになります。

Edit://Firefox の about:config ページには、私が達成したいものに非常に近いものがあります

4

4 に答える 4

6

IDictionary を実装し、Dictionary をプライベート変数として使用する新しいクラスを作成してみませんか。

次に、追加メソッドで、独自のロジックを提供し、それに応じて失敗することができます

サンプルコード

public class MyDic : IDictionary<object, object>
{
    private Dictionary<object, object> privateDic= new Dictionary<object,object>();


    public void Add(object key, object value)
    {
        if (value.GetType() == typeof(string))
            throw new ArgumentException();
        privateDic.Add(key, value);
    }
    //Rest of the interface follows
}
于 2013-03-28T17:54:43.587 に答える
0

私は次のことをお勧めします:

  1. MyDictionaryBaseType など、辞書値のベース タイプを作成します。
  2. StringDictionryType : MyDictionaryBaseType、IntegerDictionryType : MyDictionaryBaseType など、辞書の値の型ごとにこの基本型を拡張します。
  3. MyDictionaryBaseType を使用してジェネリック ディクショナリ型を作成し、型を制限してこの基本型を拡張します。

このようにして、辞書を3つの指定されたタイプに制限します

于 2013-03-28T17:42:30.573 に答える
0

次のように値をラッパー クラスに入れることができます。

class Value
{
}

class TypedValue<T> : Value
{
  public T Val;
}

class IntValue : TypedValue<int>
{
}

class StringValue : TypedValue<string>
{
}

class BoolValue : TypedValue<bool>
{
}

Dictionary<string,Value> foo;

foo.Add("key1", new StringValue{Val="Hello World!"});

もう 1 つの可能性は、Dictionary を使用して、追加された正しいタイプまたは間違ったタイプの実行時チェックを行うことです。ボクシングを使わずに解決策はないと思います。

于 2013-03-28T17:59:59.190 に答える
0

あなたが達成しようとしていることは、現状ではタイプセーフではありません。たとえば、次のような辞書があるとします。

var foo = new Dictionary<string, (string, int, bool)>();
var x = foo["key1"];
// What type is x? How could the compiler know?

string1 つのアイデアは、 、int、またはのいずれかを保持できるコンテナ クラスを考案することboolです。

public class StringIntBool {
   private bool _isSet;
   private bool _isString;
   public bool IsString {
       get { return _isString; }
   }
   // ...

   private string _innerString;
   public string InnerString {
       get {
           return _innerString;
       }
       set {
           if (_isSet) {
               throw new Exception("StringIntBool is already set");
           }
           _isSet = true;
           _isString = true;
           _innerString = value;
       }
   }

   // etc...
}

これは非常に見苦しく、あまりメリットがありません。

別の方法として、実際には 3 つの値すべてを s として保存し、 Functional C#objectのような手法/ライブラリを使用して、多くの関数型言語と同様にパターン マッチングを実行することもできます。

object x = "str";
int res = x.Match()
    .With<string>(s => s == "str" ? 10 : 20)
    .With<int>(i => i)
    .With<bool>(b => b ? 50 : 60)
    .Return<int>();

このプログラミングのパターンは、特定の関数型言語では実際にはかなり一般的です。たとえば、SML では、データ型を定義し、必要に応じてパターン マッチを行うことができます。

(* StringIntBool *)
datatype sib = SibString of string | SibInt of int | SibBool of bool

val x = (* some instance of sib *)
val y = case x of
    SibString s => if s = "hello" then 50 else -50
  | SibInt i => i
  | SibBool b => if b then 10 else 20
于 2013-03-28T18:01:08.783 に答える