簡體   English   中英

如何將抽象類轉換為類型 T?

[英]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”運算符一起使用,因為它沒有類類型約束也沒有“類”約束

不要使用as來檢查類型。 用途is代替:

if (item is T)
    return (T)item;

這里是 msdn 中關於類型轉換的詳細解釋。

為了使您的代碼工作,您必須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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM