2009-08-27 9 views
18

I tiene un MyClass clase, y me gustaría para anular el método toString() de instancias de lista:ToString Overriding() de la Lista <MyClass>

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

me gustaría tener lo siguiente:

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

¿Es posible hacerlo? O tendría que subclasificar la lista < MyClass> para reemplazar el método ToString() en mi subclase? ¿Puedo resolver este problema usando métodos de extensión (es decir, ¿es posible anular un método con un método de extensión)?

Gracias!

+0

Para información: estaba tratando de hacer algo relacionado con NHibernate, y el mapeo de colecciones en una cadena serializada que se ajustaría a una sola columna. Sin embargo, encontré otra manera de hacerlo, implementando mi propio IUserType, ¡y mi implementación construye la cadena como lo necesito! ¡Gracias a todos los que respondieron de todos modos! –

Respuesta

21

Deberá crear una subclase para anular cualquier método. El objetivo de los genéricos es decir que desea el mismo comportamiento independientemente del tipo de T. Si desea un comportamiento diferente para un tipo específico de T, está rompiendo ese contrato y tendrá que escribir su propia clase:

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

Editado para agregar:

no, no puede reemplazar un método mediante la creación de una extensión, pero se podría crear un nuevo método con una firma diferente que es específica para este tipo de lista:

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

Se utiliza con

sigo pensando que es mejor subclases aunque ...

+1

Este es un código tan pequeño para la nueva clase de lista, así que lo incluiría en la parte superior en el mismo archivo de código que la clase 'MyClass'. Así que esto no es mucho esfuerzo adicional para hacer, incluso si suena complicado crear una nueva clase, realmente no es porque la mayoría de la funcionalidad se hereda de la clase 'List' ... – awe

+0

** Acerca de la extensión método: ** Acepto que en este caso debe ir con las subclases, porque el método 'ToString' es lógicamente lo que quiere, y' List' no tiene una implementación predeterminada muy útil. La extensión agregaría un nuevo método y dejaría allí el método 'ToString' tan inútil como lo ha sido siempre para la clase genérica' List'. – awe

0

Usted tendría que crear su propia clase personalizada que hereda de Collection y luego overwride el método ToString() de esa clase específicamente

2

Si su método debe llamarse ToString, deberá derivar una clase de List. Puede que sea un genérico:

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

En este caso, habría que utilizar en lugar de MyListList a través de su aplicación si desea que su conversión personalizada.

Sin embargo, si se puede elegir un nombre diferente para su método, puede utilizar los métodos de extensión y lograr el mismo efecto, casi sin modificaciones a su código:

Puede utilizar los métodos de extensión para hacer esto más genérica :

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

se puede utilizar en cualquier instancia de IEnumerable<T> como si se tratara de un método ordinario:

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

no no es un p posible. ToString of TList le dará la representación de cadena del objeto list.

Las opciones son:

  • Derivar TList y reemplazar el método ToString() como usted ha mencionado.(en este ejemplo, no diría que vale la pena hacerlo)
  • Cree un método auxiliar que convierta una lista TList en una cadena delimitada por comas, p. método de extensión (probablemente la mejor sugerencia)
  • Utilice una instrucción foreach en la etapa Console.WriteLine.

Espero que ayude!

21

Tal vez un poco fuera de tema, pero yo uso un método de extensión ToDelimitedString que funciona para cualquier IEnumerable<T>. Se puede (opcionalmente) especificar el delimitador de usar y un delegado para llevar a cabo una conversión de cadena personalizada para cada elemento:

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

Buena sugerencia en general: yo también uso este método de extensión. Dependiendo del contexto exacto de la pregunta original, esta podría o no ser una respuesta válida aquí. – peSHIr

+0

Estos son algunos métodos de extensión realmente útiles, ¡gracias! Me ayudó a cargar dentro de una función utilizando un IList de enum tipos anónimos para convertirlos a una lista separada por comas, acaba de utilizar (x => ((corto) Convert.ChangeType (x, TypeCode.Int16)) como parámetro de mi convertidor. Gracias de nuevo Luke –

+0

Según comentario de danrichardson, gracias por la entrada esto es bastante útil! –

0

Según el motivo exacto que tiene para querer anular List<T>.ToString() para devolver algo específico que podría ser útil echar un vistazo a las implementaciones personalizadas de TypeConverter.

Si simplemente desea una List<T> de T específica a manifestarse cierta manera como un string en lugares donde se utilizan TypeConverters, al igual que en el depurador o en situaciones de tipo string.Format("List: {0}", listVariable), esto podría ser suficiente.

Es posible que haya visto el resultado de ToString() que se muestra en algún lugar y desea cambiar eso, sin saber la existencia de TypeConverter y las ubicaciones donde se utilizan. Creo que muchos/la mayoría/todos (¿no estoy seguro de cuál?) De TypeConverters predeterminados en .NET Framework simplemente usan ToString() al convertir cualquier tipo para el que están definidos a un string.

2

Puede utilizar un truco Unicode para permitirle definir un método ToString alternativo directamente en su lista genérica.

Si habilita la entrada de caracteres hexagonal en el estudio visual a continuación, puede crear personajes invisibles manteniendo pulsada la tecla Alt, y luego pulsando el siguiente en el teclado numérico + FFF 9 (ahora liberar Alt)

Así que puede crear la siguiente función con un personaje invisible colocado junto a su nombre ... (sí sé que es código de VB, pero el concepto sigue siendo el trabajo a trabajar para C#)

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

Ahora en el estudio visual, cuando se accede a intelisense contra su lista, podrá elegir entre el ToString estándar o su función personalizada.


Para permitir la entrada de caracteres hexagonal en el estudio visual puede que tenga que modificar el registro de

abierta HKEY_CURRENT_USER \ Control Panel \ métodos de entrada y crear un REG_SZ llamado EnableHexNumpad pone a 1

Usted también deberá deshabilitar los accesos directos & para los menús Archivo, Edición, Depuración, Datos, En Visual Studio, abra el menú de herramientas, seleccione personalizar, abra la pestaña de comandos y use el botón de modificación de selección para cualquier elemento de menú que use cualquiera de los ABCDEF Charactes para su atajo, eliminando el &

De lo contrario, terminará abriendo menús emergentes, en lugar de escribir caracteres hexadecimales.

+0

esto es asqueroso y tu respuesta debería ser eliminada para toda la eternidad .... +1 –

+1

Idk si funciona, pero suena ingenioso y me dio una buena risa! +1 –

Cuestiones relacionadas