[英]How to cast abstract class into type T?
我有一個抽象類:
abstract class A {
// some stuff
float val = 0;
abstract float Foo();
}
class B1 : A {
override float Foo() {
Console.WriteLine("B1: " + val);
}
}
class B2 : A {
override float Foo() {
Console.WriteLine("B2: " + val);
}
}
並且我有一個List<A> a
並且我想獲得給定類型 T 的第一項:
public T GetTypeFromList<T>() {
foreach (var item in a) {
T tmp = item as T; // doesn't compile
if (tmp != null)
return tmp;
}
throw new Exception("Type isn't in list.");
}
有沒有辦法做到這一點?
編輯:
它顯示:類型參數“T”不能與“as”運算符一起使用,因為它沒有類類型約束也沒有“類”約束
為了使您的代碼工作,您必須where
方法中添加where
約束:
static T GetTypeFromList<T>(List<A> a) where T: class
然后它將起作用。
因為,當您使用as
關鍵字時,它將對象轉換為給定的引用或可為空的值類型。 如果轉換失敗, as
運算符的結果將為null
。 而null
僅對可空類型有效。 為了讓編譯器滿意,您必須在方法簽名中添加class
約束。
但是,為此目的, System.Linq
命名空間中已經有內置方法退出。 它被稱為OfType<>
。 它根據指定的類型過濾IEnumerable
的元素。
var b2s = list.OfType<B2>();
為了獲取第一項,您可以使用First()
或FirstOrDefault()
如果集合中不存在此類元素,則將返回null
:
var b2 = list.OfType<B2>().FirstOrDefault(); // or First()
順便說一下,如果你看一下OfTypeIterator
OfType<>
的實現,你會看到它返回OfTypeIterator
並且在該方法中它只是迭代集合並使用is
運算符來找出具有所需類型的對象:
static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source) {
foreach (object obj in source) {
if (obj is TResult) yield return (TResult)obj;
}
}
最后要注意的是,在這種情況下使用as
關鍵字將提供更好的性能。 但是在OfType<>
情況下,首先使用is
運算符來檢查類型,然后會發生轉換。 因此,如果性能對您很重要,您可以繼續使用您自己的實現。
一種方法是使用 LINQ .First
方法。 您可以檢查每個元素的類型並返回T
類型的第一個元素。 如果沒有找到元素, .First
拋出異常:
List<A> myList;
var obj = (MyTargetType)myList.First(e => e is MyTargetType);
順便說一句:您只能將 operator as
用於reference 和 nullable types 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.