請看下面的代碼。為什么會出現編譯錯誤?
我不明白!
強制轉換是一種告訴編譯器我比它更了解物件的方式。在這種情況下,我知道事實上,“x”確實包含“SomeClass”的一個實體。但是編譯器似乎不愿意接受這些資訊。
https://dotnetfiddle.net/0DlmXf
public class StrangeConversion
{
public class SomeClass { }
public interface ISomeInterface { }
public class Implementation : SomeClass, ISomeInterface { }
public void Foo<T>() where T : class
{
T x = (T)Factory();
//Compile-error: Cannot convert type 'T' to 'SomeClass'
SomeClass a = (SomeClass)x;
//This is perfectly fine:
SomeClass b = (SomeClass)(object)x;
if (x is SomeClass c)
{
//This works as well and 'c' contains the reference.
}
}
private object Factory()
{
return new Implementation();
}
}
編輯:@Charles Mager 在評論中有正確答案:似乎沒有正當理由。語言設計者只是不想允許這種演員表。
uj5u.com熱心網友回復:
我使用as鑄件固定,例如
SomeClass a = x as SomeClass;
這個答案解釋得很好https://stackoverflow.com/a/132467/16690008
T本質上是因為如果不是該類的型別,它將引發例外
uj5u.com熱心網友回復:
很難準確理解您要實作的目標,但您所追求的似乎是通用約束
public void Foo<T>()
where T : SomeClass // constrain T to be inheriting from SomeClass
{
T x = Factory<T>(); // x is guaranted to be SomeClass
}
private T Factory<T>()
where T : SomeClass // same here
{
return new Implementation();
}
uj5u.com熱心網友回復:
您可以通過指定將泛型限制為僅參考型別where T : class,但編譯器需要確定是否可以進行強制轉換。這意味著您要求編譯器相信SomeClass可以從您傳遞給它的任何參考型別中強制轉換,這是它不會做的事情。微軟檔案指出,對于泛型class型別約束:
型別引數必須是參考型別。此約束也適用于任何類、介面、委托或陣列型別。
重要的是要注意,SomeClass b = (SomeClass)(object)x;因為轉換為物件層次結構object的根而起作用。但是從支持的參考型別串列中可以看出,必須考慮委托、陣列型別等,此時編譯器會拋出錯誤SomeClass a = (SomeClass)x;
不要這樣做SomeClass b = (SomeClass)(object)x;,正確使用型別約束以及為型別檢查和安全轉換的確切目的而設計的as&運算子要干凈得多is
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/454776.html
