程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> Effective C#原則5:始終提供ToString()(3)

Effective C#原則5:始終提供ToString()(3)

編輯:關於C語言

譯注:上面的做法顯然不合理,要是我的 對象有10個成員,這樣的組合是會讓人瘋掉的。推薦使用正則表達式來完成這樣 的工作,正則表達式在處理文字時的表現還是很出色的。)

添加了這樣的 函數後,你就讓用戶具有了可以這樣指定customer數據的能力:

IFormattable c1 = new Customer();
Console.WriteLine( "Customer record: {0}",
  c1.ToString( "nrp", null ) );

任何對IFormattable.ToString()的實現都要指明類型,但不管你在什麼時候 實現IFormattation接口,你都要注意處理大小寫。首先,你必須支持能用格式 化字符:“G”。其次,你必須支持兩個空格式化字符: ""和null。當你重載Object.ToString()這個方法時,這三個格式化 字符應該返回同樣的字符串。.Net的FCL經常用null來調用 IFormattable.ToString()方法,來取代對Object.ToString()的調用,但在少數 地方使用格式符"G"來格式化字符串,從而區別通用的格式。如果你 添加了對IFormattable接口的支持,並不再支持標准的格式化,你將會破壞FCL 裡的字符串的自動(隱式)轉換。

IFormattable.ToString()的第二個參數 是一個實現了IFormatProvider接口的對象。這個對象為用戶提供了一些你沒有 預先設置的格式化選項(譯注:簡單一點,就是你可以只實現你自己的格式化選 項,其它的默認由它來完成)。如果你查看一下前面IFormattable.ToString()的 實現,你就會毫不猶豫的拿出不計其數的,任何你喜歡的格式化選項,而這些都 是的格式化中所沒有的。支持人們容易閱讀的輸出是很自然的事,但不管你支持 多少種格式,你的用戶總有一天會想要你預先沒想到的格式。這就為什麼這個方 法的前幾行要檢察實現了IFormatProvider的對象,並把ICustomFormatter的工 作委托給它了。

讓我們把(討論的)焦點從類的作者轉移到類的使用者上 來。你發現你想要的格式化不被支持。例如,你有一個一組客戶,他們的名字有 的大於20個字符,並且你想修改格式化選項,讓它支持50個字符長的客戶名。這 就是為什麼IFormatProvider接口要存在。你可以設計一個實現了 IFormatProvider的類,並且讓它同時實現ICustomFormatter接口用於格式化輸 出。IFormatProvider接口定義了一個方法:GetFormat()。這個方法返回一個實 現了ICustomFormatter接口的對象。由ICustomFormatter接口的指定方法來完成 實際的格式化工作。下面這一對(接口)實現了對輸出的修改,讓它可以支持50個 字符長的用戶名:

// Example IFormatProvider:
public class CustomFormatter : IFormatProvider
{
  #region IFormatProvider Members
  // IFormatProvider contains one method.
  // This method returns an object that
  // formats using the requested interface.
  // Typically, only the ICustomFormatter
  // is implemented
  public object GetFormat( Type formatType )
  {
   if ( formatType == typeof( ICustomFormatter ))
    return new CustomerFormatProvider( );
   return null;
  }
  #endregion
 // Nested class to provide the
  // custom formatting for the Customer class.
  private class CustomerFormatProvider : ICustomFormatter
  {
   #region ICustomFormatter Members
   public string Format( string format, object arg,
    IFormatProvider formatProvider )
   {
    Customer c = arg as Customer;
    if ( c == null )
     return arg.ToString( );
    return string.Format( "{0,50}, {1,15}, {2,10:C} ",
     c.Name, c.ContactPhone, c.Revenue );
   }
   #endregion
  }
}

GetFormat()方法取得一個實現了ICustomFormatter接口的對象。而 ICustomFormatter.Format()方法,則根據用戶需求負責實際的格式化輸出工作 。這個方法把對象轉換成格式化的字符串。你可以為ICustomFormatter.Format ()定義格式化字符串,因此你可以按常規指定多重格式。FormatProvider就是一 個由GetFormat()方法取得的IFormatProvider對象。

為了滿足用戶的格 式化要求,你必須用IFormatProvider對象明確的調用string.Format()方 法:

Console.WriteLine( string.Format( new CustomFormatter (), "", c1 ));

你可以設計一個類,讓它實現IFormatProvider和ICustomFormatter接口,再 實現或者不實現IFormattable 接口。因此,即使這個類的作者沒有提供合理的 ToStrying行為,你可以自己來完成。當然,從類的外面來實現,你只能訪問公 共屬性成數據來取得字符串。實現兩個接口,IFormatProvider 和 IcustomFormatter, 只做一些文字輸出,並不需要很多工作。但在.Net框架裡, 你所實現的指定的文字輸出在哪裡都可以得到很好的支持。

所以,再回 到類的作者上來。重寫Object.ToString(),為你的類提供一些說明是件很簡單 的事。你每次都應該為你的類型提供這樣的支持。而且這應該是對你的類型最顯 而易見的,最常用的說明。在一些極端情況下,你的格式化不能支持一些過於靈 活的輸出時,你應該借用IFormattable接口的優勢。它為你的類型進行自定義格 式化輸出提供了標准方法。如果你放棄這些,你的用戶將失去用於實現自定義格 式化的工具。這些解決辦法須要寫更多的代碼,並且因為你的用戶是在類的外面 的,所以他們無法檢查類的裡面的狀態。

最後,大家注意到你的類型的 信息,他們會明白輸出的文字。盡可能以簡單的方式的提供這樣的信息吧:為你 的所有類型重寫ToString()方法。

返回教程目錄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved