覆盖List <myclass> </myclass>的ToString()

时间:2009-08-27 10:18:37

标签: c# string extension-methods override tostring

我有一个MyClass类,我想覆盖List实例的ToString()方法:

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 */

有可能这样做吗?或者我必须继承List&lt; MyClass&gt;覆盖我的子类中的方法ToString()?我可以使用扩展方法解决这个问题(即,是否可以使用扩展方法覆盖方法)?

谢谢!

7 个答案:

答案 0 :(得分:24)

也许有点偏离主题,但我使用的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());
    }
}

答案 1 :(得分:23)

您需要子类来覆盖任何方法。泛型的意思是说你想要相同的行为而不管T的类型。如果你想要特定类型的T的不同行为,那么你打破了这个合同并且需要编写你自己的类:

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

编辑添加:

不,您不能通过创建扩展来覆盖方法,但您可以创建一个具有特定于此列表类型的不同签名的新方法:

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

一起使用
List<MyClass> myClassList = new List<MyClass>
string output = myClassList.ExtendedToString();

我仍然认为你最好继承子类......

答案 2 :(得分:3)

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

如果在visual studio中启用十六进制字符输入,则可以通过按住Alt键创建不可见字符,然后在数字小键盘上按下以下按钮+ F F F 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中,当您根据列表访问intellisense时,您可以在标准ToString或自定义函数之间进行选择。


要在visual studio中启用十六进制字符输入,您可能需要编辑注册表

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

你还需要禁用&amp;文件,编辑,调试,数据菜单的快捷方式, 在visual studio中,打开工具菜单,选择自定义,然后打开命令选项卡,并使用任何菜单项的修改选择按钮,使用任何ABCDEF字符进行快捷方式,删除&amp;

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

答案 3 :(得分: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());

答案 4 :(得分:0)

您必须创建自己的继承自Collection的自定义类,然后专门覆盖该类的ToString()方法。

答案 5 :(得分:0)

不可能。 TList的ToString将为您提供列表对象的字符串表示。

您的选择是:

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

希望有所帮助!

答案 6 :(得分:0)

根据您想要覆盖List<T>.ToString()以返回特定内容的确切原因,查看自定义TypeConverter实现可能很方便。

如果您只是希望特定List<T>的{​​{1}}在使用TypeConverters的位置以T显示某种方式,例如在调试器或{{1}中}类型情况,这可能就足够了。

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