[英]C# Generic method that can infer its type argument from expression parameter
[英]Can't infer type in generic tostring method C#
我有一个自定义辅助方法,它接受一个值,并确定其类型。 如果它是一个可以枚举的数据结构,那么它将被传递到其各自的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]
。 而不是列表的内容。
快速修复您的解决方案(将值转换为其类型):
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();
您不需要在此处使用泛型,您可以使用非泛型集合接口定义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。
以防万一,如果你试图生成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))
+ "}";
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.