web-dev-qa-db-ja.com

List <MyClass>の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 */

そうすることは可能ですか?または、サブクラスのメソッドToString()をオーバーライドするには、List <MyClass>をサブクラス化する必要がありますか?拡張メソッドを使用してこの問題を解決できますか(つまり、メソッドを拡張メソッドでオーバーライドすることは可能ですか)?

ありがとう!

23
Bruno Reis

メソッドをオーバーライドするには、サブクラス化する必要があります。ジェネリックスのポイントは、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();

私はまだあなたがサブクラス化したほうがいいと思います...

24
Martin Harris

おそらく少し話題から外れていますが、私は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());
    }
}
26
LukeH

実際には、Unicodeトリックを使用して、汎用リストに対して直接代替ToStringメソッドを定義できます。

Visual Studioへの16進文字入力を有効にすると、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で、リストに対してインテリセンスにアクセスすると、標準のToStringまたはカスタム関数のいずれかを選択できるようになります。


Visual Studioへの16進文字の入力を有効にするには、レジストリを編集する必要がある場合があります

hKEY_CURRENT_USER\Control Panel\Input Methodを開き、EnableHexNumpadというREG_SZを作成して、これを1に設定します。

また、[ファイル]、[編集]、[デバッグ]、[データ]メニューの&ショートカットを無効にする必要があります。VisualStudioで、ツールメニューを開き、[カスタマイズ]を選択してから、[コマンド]タブを開き、を使用するメニュー項目の[選択の変更]ボタンを使用します。 &を削除することにより、ABCDEFのいずれかのショートカットの特性

そうしないと、16進文字を入力する代わりに、ポップアップメニューを開くことになります。

3
Richard Lee

メソッドに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());
2
Bojan Resnik

いいえ、不可能です。 TListのToStringは、リストオブジェクトの文字列表現を提供します。

オプションは次のとおりです。

  • TListから派生し、前述のように.ToString()メソッドをオーバーライドします。 (この例では、そうする価値があるとは言いません)
  • TListリストをカンマ区切りの文字列に変換するヘルパーメソッドを作成します。拡張方法(おそらく最良の提案)
  • Console.WriteLineステージでforeachステートメントを使用します。

お役に立てば幸いです。

0
James

List<T>.ToString()をオーバーライドして特定の何かを返す必要がある正確な理由によっては、カスタム TypeConverter 実装を確認すると便利な場合があります。

特定のTList<T>が、デバッガーやstring.Format("List: {0}", listVariable)のように、TypeConvertersが使用される場所でstringとして特定の方法で表示されるようにしたい場合。タイプの状況では、これで十分かもしれません。

ToString()の結果がどこかに表示されているのを見て、TypeConverterの存在とそれらが使用されている場所を知らずに、それを変更したいと思ったかもしれません。 .NET FrameworkのデフォルトのTypeConverterの多く/ほとんど/すべて(どれかわからない?)は、定義されている型をstringに変換するときに、単にToString()を使用すると思います。

0
peSHIr

Collectionから継承する独自のカスタムクラスを作成してから、そのクラスのToString()メソッドを具体的にオーバーライドする必要があります。

0
Robban