C#的out屬性

第一次接觸..因此做筆記研究一下..

out 參數修飾詞


out 關鍵字會導致引數由參考傳遞。 

它類似於 ref 關鍵字,只是 ref 需要在傳遞之前,先初始化變數。
 若要使用 out 參數,方法定義和呼叫方法都必須明確地使用 out 關鍵字。

 例如:

using System;

class OutExample
{
   static void Method(out int i)
   {
      i = 44;
   }
   
   static void Main()
   {
      int value;
      Method(out value);
      Console.WriteLine(value);     // value is now 44
   }
}

out 關鍵字也可以和泛型型別參數一起使用,指定型別參數為 Covariant。 
如需在此內容中使用 out 關鍵字的詳細資訊,請參閱 out (泛型修飾詞)

當作 out 引數傳遞的變數不必先初始化,再於方法呼叫中傳遞。 
不過,需要先指派值給被呼叫的方法,方法才能傳回。

雖然 ref 和 out 關鍵字會導致不同的執行階段行為,但在編譯階段,不會將其視為方法簽章的一部分。 因此,如果唯一的差別是一種方法採用 ref 引數,而另一種方法採用 out 引數,則不能多載方法。 

例如,將不會編譯下列程式碼:

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

不過,如果一種方法採用 ref 或 out 引數,而另一種方法都不採用,則可以完成多載,如下所示:

class OutOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(out int i) { i = 5; }
}

屬性不是變數,因此無法做為 out 參數傳遞。

如需傳遞陣列的資訊,請參閱使用 ref 和 out 傳遞陣列。

您不能將 ref 和 out 關鍵字用於下列幾種方法:
1. 使用 async 修飾詞定義的 async 方法。
2. 迭代器方法,其包括 yield return 或 yield break 陳述式。

宣告 out 引數

當您想要方法傳回多個值時,宣告使用 out 引數的方法很有用。 

下列範例使用 out,在單一方法呼叫中,傳回三個變數。 
請注意,第三個引數指派為 null。 這可讓方法能選擇性地傳回值

class OutReturnExample
{
    static void Method(out int i, out string s1, out string s2)
    {
        i = 44;
        s1 = "I've been returned";
        s2 = null;
    }

    static void Main()
    {
        int value;
        string str1, str2;
        Method(out value, out str1, out str2);
        // value is now 44
        // str1 is now "I've been returned"
        // str2 is (still) null;
    }
}

Try 模式 牽涉到傳回 bool 指出作業成功或失敗,並傳回作業在 out 引數中產生的值。 
有數種剖析方法 (例如 DateTime.TryParse 方法) 使用此模式。

呼叫有 out 引數的方法

在 C# 6 和舊版中,您必須先在其他陳述式中宣告變數,再將它傳遞為 out 引數。 
下列範例宣告名為 number 的變數,然後將它傳遞到 Int32.TryParse 方法,此方法嘗試將字串轉換為數字。

using System;

public class Example
{
   public static void Main()
   {
      string value = "1640";

      int number;
      if (Int32.TryParse(value, out number))
         Console.WriteLine($"Converted '{value}' to {number}");
      else
         Console.WriteLine($"Unable to convert '{value}'");   
   }
}
// The example displays the following output:
//       Converted '1640' to 1640

從 C# 7 開始,您可以在方法呼叫的引數清單中宣告 out 變數,而非在其他的變數中宣告。 

這會產生更精簡、更容易閱讀的程式碼,也可避免不小心在方法呼叫前先將值指派給變數。 

下列範例與上一個範例類似,但下列範例會在對 Int32.TryParse 方法的呼叫中定義 number 變數

using System;

public class Example
{
   public static void Main()
   {
      string value = "1640";

      if (Int32.TryParse(value, out int number))
         Console.WriteLine($"Converted '{value}' to {number}");
      else
         Console.WriteLine($"Unable to convert '{value}'");   
   }
}
// The example displays the following output:
//       Converted '1640' to 1640

out (泛型修飾詞)



若為泛型型別參數,out 關鍵字會指定型別參數是 Covariant。 

您可以在泛型介面委派中使用 out 關鍵字。

共變數可讓您使用比泛型參數指定的衍生程度更高的衍生型別。 

這可隱含轉換實作 Variant 介面的類別和隱含轉換委派型別。 

參考型別支援共變數和反變數,但實值型別不支援它們。

具有 Covariant 型別參數的介面可讓其方法傳回的衍生型別,衍生程度高過型別參數指定的衍生型別。 

例如,因為在 .NET Framework 4 的 IEnumerable<T> 中,T 類型是 Covariant,所以您可以不使用任何特殊的轉換方法,將 IEnumerabe(Of String) 類型的物件指派給 IEnumerable(Of Object) 類型的物件。

Covariant 委派可以指派給同型別的另一個委派,但具有衍生程度較大的泛型型別參數。

如需詳細資訊,請參閱 Covariance and Contravariance (共變數和反變數 (C# 和 Visual Basic))。

範例

下例會示範如何宣告、擴充及實作 Covariant 泛型介面。

 它也會示範如何針對實作 Covariant 介面的類別使用隱含轉換。

// Covariant interface.
interface ICovariant<out R> { }

// Extending covariant interface.
interface IExtCovariant<out R> : ICovariant<R> { }

// Implementing covariant interface.
class Sample<R> : ICovariant<R> { }

class Program
{
    static void Test()
    {
        ICovariant<Object> iobj = new Sample<Object>();
        ICovariant<String> istr = new Sample<String>();

        // You can assign istr to iobj because
        // the ICovariant interface is covariant.
        iobj = istr;
    }
}

在泛型介面中,型別參數如果滿足下列條件即可宣告為 Covariant︰

型別參數僅用為介面方法的傳回型別,不用為方法引數的型別。

注意

這個規則只有一個例外。 

如果您在 Covariant 介面中以 Contravariant 泛型委派作為方法參數,則可將 Covariant 型別用為此委派的泛型型別參數

如需 Covariant 和 Contravariant 泛型委派的詳細資訊,請參閱 Variance in Delegates (委派中的變異數) 和 Using Variance for Func and Action Generic Delegates (針對 Func 與 Action 委派使用變異數)。

型別參數不是用為介面方法的泛型條件約束。

範例

下例會示範如何宣告、具現化及叫用 Covariant 泛型委派。 
它也會顯示如何以隱含方式轉換委派型別。


// Covariant delegate.
public delegate R DCovariant<out R>();

// Methods that match the delegate signature.
public static Control SampleControl()
{ return new Control(); }

public static Button SampleButton()
{ return new Button(); }

public void Test()
{            
    // Instantiate the delegates with the methods.
    DCovariant<Control> dControl = SampleControl;
    DCovariant<Button> dButton = SampleButton;

    // You can assign dButton to dControl
    // because the DCovariant delegate is covariant.
    dControl = dButton;

    // Invoke the delegate.
    dControl(); 
}

在泛型委派中,如果型別只用為方法傳回型別,不用於方法引數,則可以宣告為 Covariant。

留言

熱門文章