0

私はこの方法を持っています

public string DictionaryToString<T, U>(Dictionary<T, U> dict)
{
  var valueStrings = dict.Select(x => x.Key.ToString() + ": " + x.Value.ToString());
  return String.Join("\n", valueStrings);
}

そして、私はそれに渡したいこのオブジェクトを持っています

if ((value !=null) && value.GetType().IsGenericType &&
  value.GetType().GetGenericTypeDefinition() == typeof (Dictionary<,>))
{
   var castValue = value as Dictionary<,>; // this cast does not work
   return DictionaryToString(castValue);
}
else
{
  return value.ToString();
}

.Net 4.5 でこのようなリフレクション コードを使用できます

var targetMethodInfo = typeof(MyType).GetMethod("DictionaryToString");
var valueTypeArgs = value.GetType().GenericTypeArguments;
var genericMethod = targetMethodInfo.MakeGenericMethod(valueTypeArgs);
var result = genericMethod.Invoke(this, new[] {value });
return result.ToString();

しかしType.GenericTypeArguments、.Net 4.5 の新機能です。では、.Net 4.0 でそのキャストを行うにはどうすればよいでしょうか。

4

5 に答える 5

3

ToStringキーと値のみを呼び出しているため、このメソッドにIDictionary(非ジェネリック) を取得させるだけで、 Torに固有の型は何も使用していませんU

IDictionary次に、すべての引数を次のように単純にキャストできます。

var d = arg as IDictionary;

if (d != null)
{
    var res = DictionaryToString(d);
}

DictionaryToString実装を修正する必要がある場合もあります。

static string DictionaryToString(IDictionary d)
{
    var vals = new List<string>();

    foreach (DictionaryEntry de in d)
    {
        vals.Add(de.Key.ToString() + ": " + de.Value.ToString());
    }

    return String.Join("\n", vals);
}

あるいは、本当に LINQ を使用したい場合は、次のようにキャストしてみてくださいdynamic(汎用辞書 ( KeyValuePair<>) または非汎用ハッシュテーブル ( DictionaryEntry) になる可能性があるため、他のものにキャストすることはできません)。

var valueStrings = d.Cast<dynamic>().Select(de => de.Key.ToString() + ": " + de.Value.ToString());
return string.Join("\n", valueStrings);

これは基本的に「アヒル型」KeyValueプロパティの存在です。

于 2012-12-12T13:36:32.870 に答える
1

これは、古いSystem.Collections名前空間の場合のように思えます。

    private static string DictionaryToString(IDictionary dict) {
        if (null == dict) throw new ArgumentNullException("dict");

        var valueStrings = new List<string>();
        foreach (DictionaryEntry item in dict) {
            valueStrings.Add(item.Key + ": " + item.Value);
        }
        return string.Join("\n", valueStrings.ToArray());
    } 

    private static string Test(object value) {

        var dict = value as IDictionary;
        if (dict != null) {
            return DictionaryToString(dict);
        }

        if (value == null) {
            return null;
        }

        return value.ToString();
    }

    private static void Main(string[] args) {

        var aDictionary = new Dictionary<int, string> {
            { 1, "one" },
            { 2, "two" },
            { 3, "three" }
        };

        Console.WriteLine(Test(aDictionary));

        var anotherDictionary = new Dictionary<string, object> {
            { "one", 1 },
            { "two", "2" },
            { "three", new object() }
        };

        Console.WriteLine(Test(anotherDictionary));

        Console.ReadLine();
    }

理由:

非ジェネリックは、キーが で値がIDictionaryであるキーと値のペアのコレクションになります。のすべてのインスタンスが をサポートしているため、コレクションのすべてのキーと値を特定の型を知らなくても に変換できます。objectobjectobjectToStringstring

これが機能しない理由:

var castValue = value as Dictionary<,>

これは、ジェネリック型Dictionary<TKey, TValue>が 2 つの型引数を必要とするためです。これらの型引数がなければ、コレクションはジェネリックではありません。IDictionaryコンパイル時にキーまたは値の型がわからない場合は、非ジェネリックを使用することをお勧めします。

于 2012-12-12T13:43:24.833 に答える
0

GetGenericTypeDefinitionは、以前のバージョンhttp://msdn.microsoft.com/en-us/library/system.type.getgenerictypedefinition(v=vs.100).aspxで使用できます。MSDNの4.5ページに「その他のバージョン」ドロップダウンがないようです。

于 2012-12-12T13:31:20.267 に答える
0

なぜだめですか?

if ((value !=null) && value.GetType().IsGenericType &&
       value.GetType().GetGenericTypeDefinition() == typeof (Dictionary<,>))
{
   return DictionaryToString(castValue);
}
else
{
  return value.ToString();
}
于 2012-12-12T13:32:08.910 に答える
0

dynamic.NET 4.0 でキャストできます。事前のtypeof(Dictionary<,>)チェックにより、実行時エラーが発生しないことが保証されます。

var castValue = value as dynamic;
return DictionaryToString(castValue);
于 2012-12-12T13:35:44.043 に答える