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!
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...
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());
}
}
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.
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());
You would have to create your own custom class that inherits from Collection and then overwride the ToString() method of that class specifically.
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!
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
.
来源:https://stackoverflow.com/questions/1340128/overriding-tostring-of-listmyclass