重写 List的 ToString()

发布于 2024-08-02 14:38:38 字数 718 浏览 5 评论 0原文

我有一个 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子类化重写我的子类中的方法 ToString() ?我可以使用扩展方法解决这个问题(即是否可以用扩展方法覆盖方法)?

谢谢!

I have a class MyClass, and I would like to override the method ToString() of instances of List:

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

I would like to have the following:

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

Is it possible to do so? Or I would have to subclass List<MyClass> to override the method ToString() in my subclass? Can I solve this problem using extension methods (ie, is it possible to override a method with an extension method)?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

听风吹 2024-08-09 14:38:39

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

如果您只是希望特定 TList 在使用 TypeConverters 的位置以某种方式显示为 string,例如在调试器或 string.Format("List: {0}", listVariable) 类型的情况下,这可能就足够了。

您可能只是在某处看到了 ToString() 的结果,并想要更改它,而不知道 TypeConverter 的存在及其使用位置。我相信 .NET Framework 中的许多/大多数/全部(不确定是哪一个?)默认 TypeConverters 在将其定义的任何类型转换为 string 时仅使用 ToString()。

Depending on the exact reason you have for wanting to override List<T>.ToString() to return something specific it might be handy to have a look at custom TypeConverter implementations.

If you simply want a List<T> of specific T to show itself a certain way as a string in locations where TypeConverters are used, like in the debugger or in string.Format("List: {0}", listVariable) type situations, this might be enough.

You might just have seen the result of ToString() being shown somewhere and wanted to change that, without knowing about the existence of TypeConverter and locations where they are used. I believe many/most/all (not sure which?) of the default TypeConverters in the .NET Framework simply use ToString() when converting any type for which they are defined for to a string.

无力看清 2024-08-09 14:38:38

也许有点偏离主题,但我使用了适用于任何 IEnumerableToDelimitedString 扩展方法。您可以(可选)指定要使用的分隔符和委托来为每个元素执行自定义字符串转换:

// 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());
    }
}

Perhaps a bit off-topic, but I use a ToDelimitedString extension method which works for any IEnumerable<T>. You can (optionally) specify the delimiter to use and a delegate to perform a custom string conversion for each element:

// 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());
    }
}
迷乱花海 2024-08-09 14:38:38

您需要子类化才能覆盖任何方法。泛型的要点是,无论 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();

我仍然认为您最好不要进行子类化...

You'll need to subclass to override any method. The point of generics is to say that you want the same behaviour regardless of the type of T. If you want different behaviour for a specific type of T then you are breaking that contract and will need to write your own class:

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

Edited to add:

No, you can't override a method by creating an extension, but you could create a new method with a different signature that is specific to this list type:

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

Used with

List<MyClass> myClassList = new List<MyClass>
string output = myClassList.ExtendedToString();

I still think you're better off subclassing though...

帝王念 2024-08-09 14:38:38

如果您的方法必须命名为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 就像普通方法一样:

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());

If you method must be named ToString you will have to derive a class from List. You can make it a generic:

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

In this case, you would have to use MyList instead of List throughout your application if you wish to have your custom conversion.

However, if you can choose a different name for your method, you can use extension methods and achieve the same effect, with almost no modifications to your code:

You can use extension methods to make this more generic:

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

You can use it on any instance of IEnumerable<T> just as if it were an ordinary method:

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());
蓝颜夕 2024-08-09 14:38:38

实际上,您可以使用 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\Control Panel\Input Method
并创建一个名为 EnableHexNumpad 的 REG_SZ 将其设置为 1

您还需要禁用 &文件、编辑、调试、数据菜单的快捷方式,
在 Visual Studio 中,打开工具菜单,选择自定义,然后打开命令选项卡,并通过删除 & 来使用任何使用 ABCDEF 字符作为快捷方式的任何菜单项的修改选择按钮。

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

You can actually use a unicode trick to allow you to define an alternate ToString method directly against your generic list.

If you enable hex character input into visual studio then you can create invisible characters by holding down the Alt key, then pressing the following on your numeric keypad + F F F 9 (now release Alt)

So we can create the following function with an invisible character placed next to its name... (yes i know its VB code, but the concept will still work work for C#)

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

Now in visual studio, when you access intellisense against your list, you will be able to choose between either the standard ToString or your custom function.


To enable hex character input into visual studio you may need to edit your registry

open HKEY_CURRENT_USER\Control Panel\Input Method
and create a REG_SZ called EnableHexNumpad set this to 1

You will also need to disable the & shortcuts for the File, Edit, Debug, Data menus,
In visual studio, open the tools menu, select customize, then open the commands tab, and using the modify selection button for any menu item that uses either of the ABCDEF charactes for its short cut, by removing the &

Otherwise you will end up opening popup menus, instead of typing hex characters.

Hello爱情风 2024-08-09 14:38:38

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

You would have to create your own custom class that inherits from Collection and then overwride the ToString() method of that class specifically.

乖乖哒 2024-08-09 14:38:38

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

您的选择是:

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

希望有帮助!

No its not possible. ToString of TList will give you the string representation of the list object.

Your options are:

  • Derive from TList and override the .ToString() method as you mentioned. (in this example I wouldn't say its worth doing so)
  • Create a helper method that converts a TList list to a comma delimited string e.g. extension method (probably best suggestion)
  • Use a foreach statement at the Console.WriteLine stage.

Hope that helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文