2009-08-27 48 views
18

我有一個類MyClass的,我想重寫列表的實例的方法ToString():重寫的ToString()<MyClass>

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

是否可以這樣做?或者我將不得不繼承列表< MyClass>重寫我的子類中的方法ToString()?我可以使用擴展方法解決這個問題嗎(例如,是否可以用擴展方法覆蓋方法)?

謝謝!

+0

有關信息:我正在嘗試做一些與NHibernate相關的事情,以及將適合單列的序列化字符串中的集合映射。然而,我發現了另一種方法來實現它,通過實現我自己的IUserType,並且我的實現根據需要構造字符串! 感謝大家誰回答! – 2009-08-27 16:25:10

回答

21

您需要繼承以覆蓋任何方法。泛型的要點在於,無論T的類型如何,您都希望獲得相同的行爲。如果您想針對特定類型的T使用不同的行爲,那麼您將違反該合同並需要編寫自己的類:

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

編輯補充:

不,你不能創建一個擴展覆蓋的方法,但你可以創建不同的簽名特定於該列表類型的新方法:

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

使用

我還是覺得你最好的子類,但...

+1

對於新的列表類,這是很少的代碼,所以我將它放在與MyClass類相同的代碼文件中。所以這並不是很多額外的努力,即使創建一個新類聽起來很複雜,但這並不是因爲大部分功能都是從List類繼承而來的...... – awe 2009-08-27 10:31:14

+0

**關於擴展方法:** 我同意在這種情況下,你應該繼續使用子類,因爲'ToString'方法在邏輯上是你想要的,'List'沒有非常有用的默認實現。 擴展會添加一個新方法,並將'ToString'方法留在那裏,就像通用的'List'類一樣無用。 – awe 2009-08-27 10:46:16

0

你將不得不創建一個從集合繼承自己的自定義類,然後的overwride的ToString()方法該類具體。

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

沒有其非p ossible。 TList的ToString將爲您提供列表對象的字符串表示形式。

的選項有:

從從TList
  • 派生和你所提到的覆蓋的ToString()方法。(在這個例子中,我不會說它值得這樣做)
  • 創建一個幫助方法,將TList列表轉換爲以逗號分隔的字符串,例如擴展方法(可能是最好的建議)
  • 在Console.WriteLine階段使用foreach語句。

希望有幫助!

21

也許有點偏題,但我使用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()); 
    } 
} 
+0

一般的好建議:我自己也使用這種擴展方法。根據原始問題的確切上下文,這可能或可能不是這裏的有效答案。 – peSHIr 2009-08-27 11:55:52

+0

這些是一些非常方便的擴展方法,謝謝! 幫助我加載一個函數內使用匿名枚舉類型的IList將它們轉換爲逗號分隔列表,只是使用(x =>((short)Convert.ChangeType(x,TypeCode.Int16))作爲我的轉換器參數。再次盧克 – 2010-06-15 11:30:16

+0

根據丹格里森評論,感謝您的輸入這是非常有用的! – 2012-07-27 10:58:06

0

取決於你有想要的確切原因覆蓋List<T>.ToString()返回一些具體的事情可能是得心應手看看自定義的TypeConverter實現。

如果你只是想具體T一個List<T>本身表現出一定的方式在類型轉換器中使用,如在調試或string.Format("List: {0}", listVariable)類型的情況下位置的string,這可能是不夠的。

您可能剛剛看到ToString()的結果顯示在某處並且想要更改該結果,但不知道TypeConverter的存在以及它們的使用位置。我相信.NET Framework中的默認TypeConverters的許多/大部分/全部(不知道哪個?)在將它們定義爲的任何類型轉換爲string時,僅使用ToString()。

2

實際上,您可以使用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 \控制面板\輸入法 並創建一個名爲REG_SZ EnableHexNumpad將其設置爲1

你還需要禁用文件,編輯,調試,數據菜單, 的快捷方式在Visual Studio中,打開工具菜單,選擇自定義,然後打開命令選項卡,然後使用所選菜單項的修改選擇按鈕ABCDEF中的任一個刪除&

否則,您將最終打開彈出式菜單,而不是輸入十六進制字符。

+0

這是令人厭惡的,你的答案應該被刪除所有永恆.... +1 – 2016-01-30 17:45:56

+1

Idk如果它的工作,但聽起來很巧妙,給了我一個很好的咯咯笑!+1 – 2017-02-21 14:43:42

相關問題