我有一个自定义辅助方法,它接受一个值,并确定其类型。如果它是一个可以枚举的数据结构,那么它将被传递到各自的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]
。而不是列表的内容。
答案 0 :(得分: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 :(得分: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重载将涵盖Array,List和IEnumerable案例。注意:需要对String进行重载,因为我们不希望将其视为IEnumberable。
答案 2 :(得分: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))
+ "}";
}
}
}