System.Object.ToString 方法

本文提供此 API 參考文件的補充備註。

Object.ToString 是 .NET 中的常見格式化方法。 它會將 對象轉換成其字串表示法,使其適合顯示。 (如需 .NET 中格式化支援的資訊,請參閱 格式化類型。)方法的預設實 Object.ToString 作會傳回物件類型的完整名稱。

重要

您可能已遵循來自另一種類型成員清單的連結來連線到此頁面。 這是因為該類型不會覆寫 Object.ToString。 相反地,它會繼承 方法的功能 Object.ToString

型別經常覆寫 Object.ToString 方法,以提供更適合特定類型的字串表示。 類型也會經常多載 Object.ToString 方法,以提供格式字串或區分文化特性格式設定的支援。

默認 Object.ToString() 方法

方法的默認實 ToString 作會傳回 型 Object別的完整名稱,如下列範例所示。

Object obj = new Object();
Console.WriteLine(obj.ToString());

// The example displays the following output:
//      System.Object
let obj = obj ()
printfn $"{obj.ToString()}"
// printfn $"{obj}" // Equivalent

// The example displays the following output:
//      System.Object
Module Example3
    Public Sub Main()
        Dim obj As New Object()
        Console.WriteLine(obj.ToString())
    End Sub
End Module
' The example displays the following output:
'      System.Object

因為 Object 是 .NET 中所有參考型別的基類,因此不會覆寫方法的 ToString 參考型別會繼承此行為。 說明如下例。 它會定義名為 Object1 的類別,以接受所有 Object 成員的默認實作。 其 ToString 方法會傳回物件的完整型別名稱。

using System;
using Examples;

namespace Examples
{
   public class Object1
   {
   }
}

public class Example5
{
   public static void Main()
   {
      object obj1 = new Object1();
      Console.WriteLine(obj1.ToString());
   }
}
// The example displays the following output:
//   Examples.Object1
type Object1() = class end

let obj1 = Object1()
printfn $"{obj1.ToString()}"
// The example displays the following output:
//   Examples.Object1
Public Class Object1
End Class

Module Example4
    Public Sub Main()
        Dim obj1 As New Object1()
        Console.WriteLine(obj1.ToString())
    End Sub
End Module
' The example displays the following output:
'   Examples.Object1

覆寫 Object.ToString() 方法

類型通常會覆寫 Object.ToString 方法,以傳回代表對象實例的字串。 例如,、和 StringCharInt32基底類型提供ToString實作,以傳回 物件所代表值的字串形式。 下列範例會定義 類別 Object2,它會覆寫 ToString 方法以傳回型別名稱及其值。

using System;

public class Object2
{
   private object value;

   public Object2(object value)
   {
      this.value = value;
   }

   public override string ToString()
   {
      return base.ToString() + ": " + value.ToString();
   }
}

public class Example6
{
   public static void Main()
   {
      Object2 obj2 = new Object2('a');
      Console.WriteLine(obj2.ToString());
   }
}
// The example displays the following output:
//       Object2: a
type Object2(value: obj) =
    inherit obj ()
    override _.ToString() =
        base.ToString() + ": " + value.ToString()

let obj2 = Object2 'a'
printfn $"{obj2.ToString()}"
// The example displays the following output:
//       Object2: a
Public Class Object2
   Private value As Object
   
   Public Sub New(value As Object)
      Me.value = value
   End Sub
   
   Public Overrides Function ToString() As String
      Return MyBase.ToString + ": " + value.ToString()
   End Function
End Class

Module Example5
    Public Sub Main()
        Dim obj2 As New Object2("a"c)
        Console.WriteLine(obj2.ToString())
    End Sub
End Module
' The example displays the following output:
'       Object2: a

下表列出 .NET 中的類型類別,並指出它們是否覆寫 Object.ToString 方法。

型別分類 Overrides Object.ToString() 行為
類別 n/a n/a
結構 是 (ValueType.ToString Object.ToString() 相同
列舉型別 是 (Enum.ToString() 成員名稱
介面 No n/a
Delegate No n/a

如需覆 ToString寫 的其他資訊,請參閱一節。

多載 ToString 方法

除了覆寫無 Object.ToString() 參數方法之外,許多類型都會多載 ToString 方法,以提供接受參數的方法版本。 最常見的方式是這樣做是為了支援變數格式設定和區分文化特性的格式。

下列範例會 ToString 多載 方法,以傳回結果字串,其中包含類別之各種欄位 Automobile 的值。 它會定義四個格式字串:G,其會傳回模型名稱和年份;D,傳回模型名稱、年份和門數:C,傳回模型名稱、年份和圓柱數;和 A,其會傳回所有四個域值的字串。

using System;

public class Automobile
{
   private int _doors;
   private string _cylinders;
   private int _year;
   private string _model;

   public Automobile(string model, int year , int doors,
                     string cylinders)
   {
      _model = model;
      _year = year;
      _doors = doors;
      _cylinders = cylinders;
   }

   public int Doors
   { get { return _doors; } }

   public string Model
   { get { return _model; } }

   public int Year
   { get { return _year; } }

   public string Cylinders
   { get { return _cylinders; } }

   public override string ToString()
   {
      return ToString("G");
   }

   public string ToString(string fmt)
   {
      if (string.IsNullOrEmpty(fmt))
         fmt = "G";

      switch (fmt.ToUpperInvariant())
      {
         case "G":
            return string.Format("{0} {1}", _year, _model);
         case "D":
            return string.Format("{0} {1}, {2} dr.",
                                 _year, _model, _doors);
         case "C":
            return string.Format("{0} {1}, {2}",
                                 _year, _model, _cylinders);
         case "A":
            return string.Format("{0} {1}, {2} dr. {3}",
                                 _year, _model, _doors, _cylinders);
         default:
            string msg = string.Format("'{0}' is an invalid format string",
                                       fmt);
            throw new ArgumentException(msg);
      }
   }
}

public class Example7
{
   public static void Main()
   {
      var auto = new Automobile("Lynx", 2016, 4, "V8");
      Console.WriteLine(auto.ToString());
      Console.WriteLine(auto.ToString("A"));
   }
}
// The example displays the following output:
//       2016 Lynx
//       2016 Lynx, 4 dr. V8
open System

type Automobile(model: string, year: int, doors: int, cylinders: string) =
    member _.Doors = doors
    member _.Model = model
    member _.Year = year
    member _.Cylinders = cylinders

    override this.ToString() =
        this.ToString "G"

    member _.ToString(fmt) =
        let fmt = 
            if String.IsNullOrEmpty fmt then "G"
            else fmt.ToUpperInvariant()

        match fmt with
        | "G" ->
            $"{year} {model}"
        | "D" ->
            $"{year} {model}, {doors} dr."
        | "C" ->
            $"{year} {model}, {cylinders}"
        | "A" ->
            $"{year} {model}, {doors} dr. {cylinders}"
        | _ ->
            raise (ArgumentException $"'{fmt}' is an invalid format string")

let auto = Automobile("Lynx", 2016, 4, "V8")
printfn $"{auto}"
printfn $"""{auto.ToString "A"}"""
// The example displays the following output:
//       2016 Lynx
//       2016 Lynx, 4 dr. V8
Public Class Automobile
   Private _doors As Integer
   Private _cylinders As String
   Private _year As Integer
   Private _model As String
   
   Public Sub New(model As String, year As Integer, doors As Integer,
                  cylinders As String)
      _model = model
      _year = year
      _doors = doors
      _cylinders = cylinders
   End Sub
   
   Public ReadOnly Property Doors As Integer
      Get
          Return _doors
      End Get
   End Property
   
   Public ReadOnly Property Model As String
      Get
         Return _model
      End Get
   End Property
   
   Public ReadOnly Property Year As Integer
      Get
         Return _year
      End Get
   End Property
   
   Public ReadOnly Property Cylinders As String
      Get
         Return _cylinders
      End Get
   End Property
   
   Public Overrides Function ToString() As String
      Return ToString("G")
   End Function
   
   Public Overloads Function ToString(fmt As String) As String
      If String.IsNullOrEmpty(fmt) Then fmt = "G"
      
      Select Case fmt.ToUpperInvariant()
         Case "G"
            Return String.Format("{0} {1}", _year, _model)
         Case "D"
            Return String.Format("{0} {1}, {2} dr.",
                                 _year, _model, _doors)
         Case "C"
            Return String.Format("{0} {1}, {2}",
                                 _year, _model, _cylinders)
         Case "A"
            Return String.Format("{0} {1}, {2} dr. {3}",
                                 _year, _model, _doors, _cylinders)
         Case Else
            Dim msg As String = String.Format("'{0}' is an invalid format string",
                                              fmt)
            Throw New ArgumentException(msg)
      End Select
   End Function
End Class

Module Example6
    Public Sub Main()
        Dim auto As New Automobile("Lynx", 2016, 4, "V8")
        Console.WriteLine(auto.ToString())
        Console.WriteLine(auto.ToString("A"))
    End Sub
End Module
' The example displays the following output:
'       2016 Lynx
'       2016 Lynx, 4 dr. V8

下列範例會呼叫 多載 Decimal.ToString(String, IFormatProvider) 方法,以顯示貨幣值的區分文化特性格式。

using System;
using System.Globalization;

public class Example8
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "en-GB", "fr-FR",
                                "hr-HR", "ja-JP" };
      Decimal value = 1603.49m;
      foreach (var cultureName in cultureNames) {
         CultureInfo culture = new CultureInfo(cultureName);
         Console.WriteLine("{0}: {1}", culture.Name,
                           value.ToString("C2", culture));
      }
   }
}
// The example displays the following output:
//       en-US: $1,603.49
//       en-GB: £1,603.49
//       fr-FR: 1 603,49 €
//       hr-HR: 1.603,49 kn
//       ja-JP: ¥1,603.49
open System.Globalization

let cultureNames =
    [| "en-US"; "en-GB"; "fr-FR"; "hr-HR"; "ja-JP" |]
let value = 1603.49m
for cultureName in cultureNames do
    let culture = CultureInfo cultureName
    printfn $"""{culture.Name}: {value.ToString("C2", culture)}"""
// The example displays the following output:
//       en-US: $1,603.49
//       en-GB: £1,603.49
//       fr-FR: 1 603,49 €
//       hr-HR: 1.603,49 kn
//       ja-JP: ¥1,603.49
Imports System.Globalization

Module Example7
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "en-GB", "fr-FR",
                                       "hr-HR", "ja-JP"}
        Dim value As Decimal = 1603.49D
        For Each cultureName In cultureNames
            Dim culture As New CultureInfo(cultureName)
            Console.WriteLine("{0}: {1}", culture.Name,
                           value.ToString("C2", culture))
        Next
    End Sub
End Module
' The example displays the following output:
'       en-US: $1,603.49
'       en-GB: £1,603.49
'       fr-FR: 1 603,49 €
'       hr-HR: 1.603,49 kn
'       ja-JP: ¥1,603.49

如需格式字串和區分文化特性格式設定的詳細資訊,請參閱 格式化類型。 如需數值所支援的格式字串,請參閱 標準數值格式字串自定義數值格式字串。 如需日期和時間值所支援的格式字串,請參閱 標準日期和時間格式字串自定義日期和時間格式字串

擴充 Object.ToString 方法

因為類型會繼承預設 Object.ToString 方法,所以您可能會發現其行為不理想,而且想要變更它。 這特別適用於數位和集合類別。 雖然您可能預期 ToString 陣列或集合類別的 方法會顯示其成員的值,但是它會改為顯示類型完整類型名稱,如下列範例所示。

int[] values = { 1, 2, 4, 8, 16, 32, 64, 128 };
Console.WriteLine(values.ToString());

List<int> list = new List<int>(values);
Console.WriteLine(list.ToString());

// The example displays the following output:
//       System.Int32[]
//       System.Collections.Generic.List`1[System.Int32]
let values = [| 1; 2; 4; 8; 16; 32; 64; 128 |]
printfn $"{values}"

let list = ResizeArray values
printfn $"{list}"

// The example displays the following output:
//       System.Int32[]
//       System.Collections.Generic.List`1[System.Int32]
Imports System.Collections.Generic

Module Example
   Public Sub Main()
      Dim values() As Integer = { 1, 2, 4, 8, 16, 32, 64, 128 }
      Console.WriteLine(values.ToString())
      
      Dim list As New List(Of Integer)(values)
      Console.WriteLine(list.ToString())
   End Sub
End Module
' The example displays the following output:
'    System.Int32[]
'    System.Collections.Generic.List`1[System.Int32]

您有數個選項可產生您想要的結果字串。

  • 如果類型是陣列、集合物件或實IEnumerable作 或 IEnumerable<T> 介面的物件,您可以使用 C# 中的 語句或 For Each...Next Visual Basic 中的 建構來列舉其元素foreach

  • 如果類別不是 sealed (在 C# 中) 或 NotInheritable (在 Visual Basic 中),您可以開發繼承自要自定義其方法之 Object.ToString 基類的包裝函式類別。 這至少需要您執行下列動作:

    1. 實作任何必要的建構函式。 衍生類別不會繼承其基類建構函式。
    2. 覆寫 Object.ToString 方法以傳回您想要的結果字串。

    下列範例會定義 類別的 List<T> 包裝函式類別。 它會覆寫 Object.ToString 方法,以顯示集合中每個方法的值,而不是完整類型名稱。

    using System;
    using System.Collections.Generic;
    
    public class CList<T> : List<T>
    {
       public CList(IEnumerable<T> collection) : base(collection)
       { }
    
       public CList() : base()
       {}
    
       public override string ToString()
       {
          string retVal = string.Empty;
          foreach (T item in this) {
             if (string.IsNullOrEmpty(retVal))
                retVal += item.ToString();
             else
                retVal += string.Format(", {0}", item);
          }
          return retVal;
       }
    }
    
    public class Example2
    {
       public static void Main()
       {
          var list2 = new CList<int>();
          list2.Add(1000);
          list2.Add(2000);
          Console.WriteLine(list2.ToString());
       }
    }
    // The example displays the following output:
    //    1000, 2000
    
    open System
    open System.Collections.Generic
    
    type CList<'T>() = 
        inherit ResizeArray<'T>()
        
        override this.ToString() =
            let mutable retVal = String.Empty
            for item in this do
                if String.IsNullOrEmpty retVal then
                    retVal <- retVal + string item
                else
                    retVal <- retVal + $", {item}"
            retVal
    
    let list2 = CList()
    list2.Add 1000
    list2.Add 2000
    printfn $"{list2}"
    // The example displays the following output:
    //    1000, 2000
    
    Imports System.Collections.Generic
    
    Public Class CList(Of T) : Inherits List(Of T)
       Public Sub New(capacity As Integer)
          MyBase.New(capacity)
       End Sub
    
       Public Sub New(collection As IEnumerable(Of T))
          MyBase.New(collection)
       End Sub
    
       Public Sub New()
          MyBase.New()
       End Sub
    
       Public Overrides Function ToString() As String
          Dim retVal As String = String.Empty
          For Each item As T In Me
             If String.IsNullOrEmpty(retval) Then
                retVal += item.ToString()
             Else
                retval += String.Format(", {0}", item)
             End If
          Next
          Return retVal
       End Function
    End Class
    
    Module Example1
        Public Sub Main()
            Dim list2 As New CList(Of Integer)
            list2.Add(1000)
            list2.Add(2000)
            Console.WriteLine(list2.ToString())
        End Sub
    End Module
    ' The example displays the following output:
    '       1000, 2000
    
  • 開發擴充方法,以傳回您想要的結果字串。 請注意,您無法以這種方式覆寫預設 Object.ToString 方法,也就是說,您的擴充類別(在 C#) 或模組 (在 Visual Basic 中) 不能有名為 ToString 的無參數方法,無法取代原始類型 ToString 的方法。 您必須為無 ToString 參數取代提供一些其他名稱。

    下列範例會定義兩個擴充 List<T> 類別的方法:無 ToString2 參數方法,以及 ToString 具有 String 表示格式字串之參數的方法。

    using System;
    using System.Collections.Generic;
    
    public static class StringExtensions
    {
       public static string ToString2<T>(this List<T> l)
       {
          string retVal = string.Empty;
          foreach (T item in l)
             retVal += string.Format("{0}{1}", string.IsNullOrEmpty(retVal) ?
                                                         "" : ", ",
                                      item);
          return string.IsNullOrEmpty(retVal) ? "{}" : "{ " + retVal + " }";
       }
    
       public static string ToString<T>(this List<T> l, string fmt)
       {
          string retVal = string.Empty;
          foreach (T item in l) {
             IFormattable ifmt = item as IFormattable;
             if (ifmt != null)
                retVal += string.Format("{0}{1}",
                                        string.IsNullOrEmpty(retVal) ?
                                           "" : ", ", ifmt.ToString(fmt, null));
             else
                retVal += ToString2(l);
          }
          return string.IsNullOrEmpty(retVal) ? "{}" : "{ " + retVal + " }";
       }
    }
    
    public class Example3
    {
       public static void Main()
       {
          List<int> list = new List<int>();
          list.Add(1000);
          list.Add(2000);
          Console.WriteLine(list.ToString2());
          Console.WriteLine(list.ToString("N0"));
       }
    }
    // The example displays the following output:
    //       { 1000, 2000 }
    //       { 1,000, 2,000 }
    
    open System
    open System.Collections.Generic
    
    type List<'T> with
        member this.ToString2<'T>() = 
            let mutable retVal = String.Empty
            for item in this do
               retVal <- retVal + $"""{if String.IsNullOrEmpty retVal then "" else ", "}{item}"""
            if String.IsNullOrEmpty retVal then "{}" else "{ " + retVal + " }"
    
        member this.ToString<'T>(fmt: string) =
            let mutable retVal = String.Empty
            for item in this do
                match box item with
                | :? IFormattable as ifmt ->
                    retVal <- retVal + $"""{if String.IsNullOrEmpty retVal then "" else ", "}{ifmt.ToString(fmt, null)}"""
                | _ ->
                    retVal <- retVal + this.ToString2()
            if String.IsNullOrEmpty retVal then "{}" else "{ " + retVal + " }"
    
    let list = ResizeArray()
    list.Add 1000
    list.Add 2000
    printfn $"{list.ToString2()}"
    printfn $"""{list.ToString "N0"}"""
    // The example displays the following output:
    //       { 1000, 2000 }
    //       { 1,000, 2,000 }
    
    Imports System.Collections.Generic
    Imports System.Runtime.CompilerServices
    
    Public Module StringExtensions
       <Extension()>
       Public Function ToString2(Of T)(l As List(Of T)) As String
          Dim retVal As String = ""
          For Each item As T In l
             retVal += String.Format("{0}{1}", If(String.IsNullOrEmpty(retVal),
                                                         "", ", "),
                                      item)
          Next
          Return If(String.IsNullOrEmpty(retVal), "{}", "{ " + retVal + " }")
       End Function
    
       <Extension()>
       Public Function ToString(Of T)(l As List(Of T), fmt As String) As String
          Dim retVal As String = String.Empty
          For Each item In l
             Dim ifmt As IFormattable = TryCast(item, IFormattable)
             If ifmt IsNot Nothing Then
                retVal += String.Format("{0}{1}",
                                        If(String.IsNullOrEmpty(retval),
                                           "", ", "), ifmt.ToString(fmt, Nothing))
             Else
                retVal += ToString2(l)
             End If
          Next
          Return If(String.IsNullOrEmpty(retVal), "{}", "{ " + retVal + " }")
       End Function
    End Module
    
    Module Example2
        Public Sub Main()
            Dim list As New List(Of Integer)
            list.Add(1000)
            list.Add(2000)
            Console.WriteLine(list.ToString2())
            Console.WriteLine(list.ToString("N0"))
        End Sub
    End Module
    ' The example displays the following output:
    '       { 1000, 2000 }
    '       { 1,000, 2,000 }
    

Windows 執行階段的注意事項

當您在 Windows 執行階段 的類別上呼叫 ToString 方法時,它會為未覆寫 ToString的類別提供預設行為。 這是 .NET 為 Windows 執行階段 提供支援的一部分(請參閱 Windows 市集應用程式和 Windows 執行階段 的 .NET 支援)。 Windows 執行階段 中的類別不會繼承 Object,而且不一定實作 ToString。 不過,當您在 C# 或 Visual Basic 程式代碼中使用、 和 方法時,它們一律會有 ToStringEquals(Object)、 和 GetHashCode 方法,而 .NET 會提供這些方法的預設行為。

Common Language Runtime 會在 Windows 執行階段 物件上使用 IStringable.ToString,然後再回到 的默認實作Object.ToString

注意

Windows 執行階段 以 C# 或 Visual Basic 撰寫的類別可以覆寫 ToString 方法。

Windows 執行階段 和 IStringable 介面

Windows 執行階段 包含 IStringable 介面,其單一方法 IStringable.ToString 提供基本格式支援,可比作 所提供的 Object.ToString。 若要避免模棱兩可,您不應該在 Managed 類型上實 作 IStringable

當 Managed 物件是由機器碼或以 JavaScript 或 C++/CX 等語言撰寫的程式代碼呼叫時,它們似乎會實 作 IStringable。 如果 Managed 物件上未實作 IStringable,Common Language Runtime 會自動將呼叫從 IStringable.ToString 路由傳送至 Object.ToString

警告

因為 Common Language Runtime 會針對 Windows 市集應用程式中的所有受控類型自動實 作 IStringable ,因此建議您不要提供自己的 IStringable 實作。 從 Windows 執行階段、C++/CX 或 JavaScript 呼叫ToString時,實作IStringable可能會導致非預期的行為。

如果您選擇在 Windows 執行階段元件中導出的公用 Managed 類型中實作 IStringable,則適用下列限制:

  • 您只能在「類別實作」關聯性中定義 IStringable 介面,如下所示:

    public class NewClass : IStringable
    
    Public Class NewClass : Implements IStringable
    
  • 您無法在介面上實 作 IStringable

  • 您無法將參數宣告為 IStringable 類型

  • IStringable 不能是方法、屬性或欄位的傳回類型。

  • 您無法使用下列方法定義,從基類隱藏 IStringable 實作:

    public class NewClass : IStringable
    {
       public new string ToString()
       {
          return "New ToString in NewClass";
       }
    }
    

    相反地 ,IStringable.ToString 實作必須一律覆寫基類實作。 您只能藉由針對強型別類別執行個體叫用 ToString 實作來隱藏該實作。

在各種情況下,從機器碼呼叫到實作 IStringable 或隱藏其 ToString 實作的 Managed 類型,可能會產生非預期的行為。