无法推断通用 tostring 方法 C# 中的类型

问题描述 投票:0回答:3

我有一个自定义辅助方法,它接受一个值并确定其类型。如果它是一个可以枚举的数据结构,那么它会被传递到其各自的

ToString
方法以进行打印。但如果没有,则调用内置的
.ToString()
方法。

public static String GetString<T> (T value)
{
    Type t = typeof(T);
    if (t.IsSubclassOf (typeof(IDictionary)))
        return _GetString_Dictionary(value);
    else if (t.IsSubclassOf (typeof(IEnumerable)))
        return _GetString_Enumerable (value);
    else
        return value.ToString ();
}

但是,我收到了很多与如何无法为每次调用其他方法推断参数类型相关的错误。对于如何解决这个问题,我目前没有主动性;还能实现吗?

下面是上面调用的其他toString方法,供参考;

private static String _GetString_Dictionary<KT, VT> (Dictionary<KT, VT> d)
{
    string s = "{";
    foreach (var pair in d)
        s += GetString(pair.Key) + " : " + GetString(pair.Value) + ", ";
    return s.Substring (0, s.Length - 2) + "}";
}

private static String _GetString_Enumerable<T> (IEnumerable<T> e)
{
    string s = "[";
    foreach (T i in e)
        s += GetString(i) + ", ";
    return s.Substring(0, s.Length-2) + "]";
}

编辑:根据 Equiso 的信息缩短代码。


根据 David Manning 的示例,我已将代码修改为如下所示;

public static String GetString<KT, VT> (Dictionary<KT, VT> d)
{
    string s = "{";
    foreach (var pair in d)
        s += GetString(pair.Key) + " : " + GetString(pair.Value) + ", ";
    return s.Substring (0, s.Length - 2) + "}";
}

public static String GetString<T> (IEnumerable<T> e)
{
    string s = "[";
    foreach (T i in e)
        s += GetString(i) + ", ";
    return s.Substring(0, s.Length-2) + "]";
}

public static String GetString<T> (T value)
{
    return value.ToString ();
}

它不再抛出错误。

编辑:它没有按预期工作;相反,它在传递给它的每个对象上调用通用的

.ToString()
版本的
GetString()
,而不是更具体的重载(如果它适用)。将
List
对象传递给它会返回字符串
System.Collections.Generic.List'1[System.String]
。而不是列表的内容。

c# types type-inference
3个回答
1
投票

您不需要在这里使用泛型,您可以使用非泛型集合接口定义

GetString
,编译器会将您的调用绑定到最具体的接口。例如:

public static String GetString(object value) {

    if (value is string) {
        return value as string;
    } else if (value is IDictionary) {
        return GetString(value as IDictionary);
    } else if (value is IEnumerable) {
        return GetString(value as IEnumerable);
    } else {
        return value.ToString();
    }
}

public static String GetString(string l) {
    return l;
}

public static String GetString(IEnumerable l) {
    string s = "[";
    foreach (object i in l) {
        s += GetString(i) + ", ";
    }
    if (s != "[") s = s.Substring(0, s.Length - 2);
    return s + "]";
}

public static String GetString(IDictionary d) {
    string s = "{";
    foreach (object key in d.Keys) {
        s += GetString(key) + " : " + GetString(d[key]) + ", ";
    }
    if (s != "{") s = s.Substring(0, s.Length - 2);
    return s + "}";
}

数组、列表和

IEnumerable<T>
情况都将被
IEnumerable
重载覆盖。注意:需要重载字符串,因为我们不想将其视为
IEnumerable<Char>


1
投票

快速修复您的解决方案(将值转换为其类型):

public static String GetString<T> (T value)
{
  Type t = typeof(T);
  if (t.IsSubclassOf (typeof(Array)) || t.IsSubclassOf (typeof(IList)))
    return _ToString_List ((List)value);
  else if (t.IsSubclassOf (typeof(IDictionary)))
    return _ToString_Dictionary((Dictionary)value);
  else if (t.IsSubclassOf (typeof(IEnumerable)))
    return _ToString_Enumerable ((IEnumerable)value);
  else
    return value.ToString ();
}

更优雅的解决方案是使用扩展方法

public static class ToStringExtension()
{
  publicstatic String MyToString<T> (this T[] a) 
  {
  if (a.Length == 0)
    return "[]";
  string s = "[";
  for (int i=0; i<a.Length - 1; i++)
    s += GetString(a [i]) + ", ";
  return s + a [a.Length - 1] + "]";
  }

  public static String MyToString<KT, VT> (this Dictionary<KT, VT> d)
  {
  string s = "{";
  foreach (var pair in d)
    s += GetString(pair.Key) + " : " + GetString(pair.Value) + ", ";
  return s.Substring (0, s.Length - 2) + "}";
  }

  public static String MyToString<T> (this IEnumerable<T> e)
  {
  string s = "[";
  foreach (T i in e)
    s += GetString(i) + ", ";
  return s.Substring(0, s.Length-2) + "]";
  }
}

使用扩展方法:

var arr = new string[10];
arr.MyToString();

1
投票

以防万一,如果您尝试生成 json,只需使用像 Json.NET 这样的库就可以省去很多麻烦,序列化对象并不像您想象的那么简单。


您可以创建具有相同名称但参数不同的方法,并且当您运行代码时,C# 将根据您作为参数传递的类型选择正确的方法来执行,您不需要测试它的类型。

您只需要两个重载,一个用于

IEnumerables
,涵盖
Lists
Arrays
,另一个用于
Dictionary

您还可以使用一些框架方法来连接字符串

string.Join
,这只会在元素之间添加分隔符,因此您不必担心删除尾随逗号。

这是一个小工作示例

using System;
using System.Collections.Generic;
using System.Linq;

namespace Experiments {
    class Program {
        static void Main(string[] args) {
            var array = new[] { "one", "two", "three" };
            var list = new List<string> { "four", "five", "six" };
            var dictionary = new Dictionary<string, string> {
                {"k1", "v1"},
                {"k2", "v2"},
                {"k3", "v2"},
            };

            Console.WriteLine(GetString(array));
            Console.WriteLine(GetString(list));
            Console.WriteLine(GetString(dictionary));

            Console.ReadLine();
        }

        public static string GetString<T>(IEnumerable<T> value) {
            return "["
                + string.Join(", ", value)
                + "]";
        }

        public static string GetString<TKey, TValue>(Dictionary<TKey, TValue> value) {
            return "{"
                + string.Join(", ", value.Select(entry => entry.Key + " : " + entry.Value))
                + "}";
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.