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。
留言
張貼留言