2009-08-27 83 views
18

我有一个类MyClass的,我想重写列表的实例的方法ToString():重写的ToString()<MyClass>

class MyClass 
{ 
    public string Property1 { get; set; } 
    public int Property2 { get; set; } 
    /* ... */ 
    public override string ToString() 
    { 
     return Property1.ToString() + "-" + Property2.ToString(); 
    } 
} 

我想有以下几点:

var list = new List<MyClass> 
      { 
       new MyClass { Property1 = "A", Property2 = 1 }, 
       new MyClass { Property1 = "Z", Property2 = 2 }, 
      }; 

Console.WriteLine(list.ToString()); /* prints: A-1,Z-2 */ 

是否可以这样做?或者我将不得不继承列表< MyClass>重写我的子类中的方法ToString()?我可以使用扩展方法解决这个问题吗(例如,是否可以用扩展方法覆盖方法)?

谢谢!

+0

有关信息:我正在尝试做一些与NHibernate相关的事情,以及将适合单列的序列化字符串中的集合映射。然而,我发现了另一种方法来实现它,通过实现我自己的IUserType,并且我的实现根据需要构造字符串! 感谢大家谁回答! – 2009-08-27 16:25:10

回答

21

您需要继承以覆盖任何方法。泛型的要点在于,无论T的类型如何,您都希望获得相同的行为。如果您想针对特定类型的T使用不同的行为,那么您将违反该合同并需要编写自己的类:

public class MyTypeList : List<MyClass> 
{ 
    public override string ToString() 
    { 
     return ... 
    } 
} 

编辑补充:

不,你不能创建一个扩展覆盖的方法,但你可以创建不同的签名特定于该列表类型的新方法:

public static string ExtendedToString(this List<MyClass> list) 
{ 
    return .... 
} 

使用

我还是觉得你最好的子类,但...

+1

对于新的列表类,这是很少的代码,所以我将它放在与MyClass类相同的代码文件中。所以这并不是很多额外的努力,即使创建一个新类听起来很复杂,但这并不是因为大部分功能都是从List类继承而来的...... – awe 2009-08-27 10:31:14

+0

**关于扩展方法:** 我同意在这种情况下,你应该继续使用子类,因为'ToString'方法在逻辑上是你想要的,'List'没有非常有用的默认实现。 扩展会添加一个新方法,并将'ToString'方法留在那里,就像通用的'List'类一样无用。 – awe 2009-08-27 10:46:16

0

你将不得不创建一个从集合继承自己的自定义类,然后的overwride的ToString()方法该类具体。

2

如果你的方法必须命名为ToString你将不得不从List派生类。你可以把它的通用:

static class MyList<T> : List<T> 
{ 
    public override string ToString() 
    { 
     // ... 
    } 
} 

在这种情况下,你将不得不使用MyList,而不是List整个应用程序中,如果您希望您的自定义转换。

但是,如果你能为你的方法选择不同的名称,则可以使用扩展方法,达到同样的效果,几乎没有修改代码:

您可以使用扩展方法,使这个更通用:

static class ListExtension 
{ 
    public static void ConvertToString<T>(this IEnumerable<T> items) 
    { 
     // ... 
    } 
} 

您可以使用它的IEnumerable<T>任何实例,就好像它是一个普通的方法:

List<MyClass> list = new List<MyClass> { ... }; 
Console.WriteLine(list.ConvertToString()); 

int[] array_of_ints = {1,2,3,4,5}; 
Console.WriteLine(array_of_ints.ConvertToString()); 
0

没有其非p ossible。 TList的ToString将为您提供列表对象的字符串表示形式。

的选项有:

从从TList
  • 派生和你所提到的覆盖的ToString()方法。(在这个例子中,我不会说它值得这样做)
  • 创建一个帮助方法,将TList列表转换为以逗号分隔的字符串,例如扩展方法(可能是最好的建议)
  • 在Console.WriteLine阶段使用foreach语句。

希望有帮助!

21

也许有点偏题,但我使用ToDelimitedString扩展方法适用于任何IEnumerable<T>。您可以(可选)指定要使用的分隔符,并委托执行的每个元素的自定义字符串转换:

// if you've already overridden ToString in your MyClass object... 
Console.WriteLine(list.ToDelimitedString()); 
// if you don't have a custom ToString method in your MyClass object... 
Console.WriteLine(list.ToDelimitedString(x => x.Property1 + "-" + x.Property2)); 

// ... 

public static class MyExtensionMethods 
{ 
    public static string ToDelimitedString<T>(this IEnumerable<T> source) 
    { 
     return source.ToDelimitedString(x => x.ToString(), 
      CultureInfo.CurrentCulture.TextInfo.ListSeparator); 
    } 

    public static string ToDelimitedString<T>(
     this IEnumerable<T> source, Func<T, string> converter) 
    { 
     return source.ToDelimitedString(converter, 
      CultureInfo.CurrentCulture.TextInfo.ListSeparator); 
    } 

    public static string ToDelimitedString<T>(
     this IEnumerable<T> source, string separator) 
    { 
     return source.ToDelimitedString(x => x.ToString(), separator); 
    } 

    public static string ToDelimitedString<T>(this IEnumerable<T> source, 
     Func<T, string> converter, string separator) 
    { 
     return string.Join(separator, source.Select(converter).ToArray()); 
    } 
} 
+0

一般的好建议:我自己也使用这种扩展方法。根据原始问题的确切上下文,这可能或可能不是这里的有效答案。 – peSHIr 2009-08-27 11:55:52

+0

这些是一些非常方便的扩展方法,谢谢! 帮助我加载一个函数内使用匿名枚举类型的IList将它们转换为逗号分隔列表,只是使用(x =>((short)Convert.ChangeType(x,TypeCode.Int16))作为我的转换器参数。再次卢克 – 2010-06-15 11:30:16

+0

根据丹格里森评论,感谢您的输入这是非常有用的! – 2012-07-27 10:58:06

0

取决于你有想要的确切原因覆盖List<T>.ToString()返回一些具体的事情可能是得心应手看看自定义的TypeConverter实现。

如果你只是想具体T一个List<T>本身表现出一定的方式在类型转换器中使用,如在调试或string.Format("List: {0}", listVariable)类型的情况下位置的string,这可能是不够的。

您可能刚刚看到ToString()的结果显示在某处并且想要更改该结果,但不知道TypeConverter的存在以及它们的使用位置。我相信.NET Framework中的默认TypeConverters的许多/大部分/全部(不知道哪个?)在将它们定义为的任何类型转换为string时,仅使用ToString()。

2

实际上,您可以使用unicode技巧来直接针对通用列表定义备用ToString方法。

如果启用十六进制字符输入到Visual Studio,那么你可以按住Alt键,然后按数字键盘上下面创建不可见的字符+ FFF 9(现在放开Alt键)

因此,我们可以创建与旁边放置它的名字有不可见字符以下功能...(是的,我知道它的VB代码,但概念仍然适用于C#的工作)

<Extension()> _ 
Public Function ToString(ByVal source As Generic.List(Of Char)) As String 
    Return String.Join(separator:="", values:=source.ToArray) 
End Function 

现在,在Visual Studio中,当您访问对智能感知您的列表,您将能够选择标准的ToString或您的自定义功能。


要启用十六进制字符输入到Visual Studio中,你可能需要编辑注册表

打开HKEY_CURRENT_USER \控制面板\输入法 并创建一个名为REG_SZ EnableHexNumpad将其设置为1

你还需要禁用文件,编辑,调试,数据菜单, 的快捷方式在Visual Studio中,打开工具菜单,选择自定义,然后打开命令选项卡,然后使用所选菜单项的修改选择按钮ABCDEF中的任一个删除&

否则,您将最终打开弹出式菜单,而不是输入十六进制字符。

+0

这是令人厌恶的,你的答案应该被删除所有永恒.... +1 – 2016-01-30 17:45:56

+1

Idk如果它的工作,但听起来很巧妙,给了我一个很好的咯咯笑!+1 – 2017-02-21 14:43:42

相关问题