我有一個非泛型IList,我想enum在運行時根據一個值進行轉換。
我無法在實作中更改非通用 IList 的型別,因為它是庫代碼。
另外我不想使用反射(因為它很慢)或動態關鍵字(因為它不安全并且可能導致錯誤)。
在庫代碼中有以下類:
public class ListView //THIS IS LIBRARY CODE AND CAN NOT BE CHANGED
{
public IList itemsSource { get; set; }
}
然后在我從 ListView 繼承的 CustomListView 類中,我想根據 ItemType 將 itemsSource 轉換為適當的類。
另一個限制是 CustomListView 不能是通用的(由我們使用的庫決定)
public class CustomListView : ListView
{
public dynamic GetItems()
{
switch (ItemType)
{
case ItemType.A:
return itemsSource.Cast<A>().ToList();
case ItemType.B:
return itemsSource.Cast<B>().ToList();
default:
throw new InvalidOperationException("Not supported");
}
}
}
但我希望它直接回傳正確的型別而不是使用動態。
類似的東西(下面的代碼不起作用!):
public IList<T> GetItems(ItemType itemType) //The type of T should change depending on what i return
{
switch (ItemType)
{
case ItemType.A:
return itemsSource.Cast<A>().ToList();
case ItemType.B:
return itemsSource.Cast<B>().ToList();
default:
throw new InvalidOperationException("Not supported");
}
}
我將如何實施?
編輯/附加
正如你們所指出的,我應該澄清一些事情。
A 類和 B 類確實具有相同的基類。但是我希望能夠不再從基型別轉換它(因為我已經在 GetItems() 方法中轉換了它并且 ItemType 的值是已知的)。
我希望能夠執行以下操作
IList<A> aItems = listView.GetItems()
沒有鑄造。
所有這一切背后的想法是擁有一個可以處理多種專案型別的通用 CustomListView。這些專案將被添加到 itemSource。這些專案的型別由 ItemType 確定。
例如,我像這樣使用它
public class UiForClassA
{
public void Foo()
{
CustomListView customListView = new CustomListView(ItemType.A);
IList<A> itemsOfCustomListView = customListView.GetItems(); //No cast needed because it should somehow implicitly know that.
}
}
我不想在我使用 CustomListView 的任何地方使用 Casts。它應該以某種方式隱式回傳正確的專案。
對于您的資訊,我使用 Unity UI 工具包框架,但這與問題并不真正相關。
uj5u.com熱心網友回復:
想想這個方法將如何使用:
ItemType itemType = ...;
var x = listView.GetItems(itemType);
的值itemType可能是A,也可能是B。那么應該是什么型別x呢?它是IList<A>或IList<B>,唯一的表達方式是使用IList<A>和IList<B>都繼承自的型別,這讓我們回到IList. 如果您在編譯時不知道您想要的型別,那么嘗試將回傳型別更改為更具體的型別沒有多大意義,因為您將無法在沒有反射的情況下將其作為更具體的型別訪問。
如果您在編譯時確實知道所需的型別,則提供回傳所需型別的方法的多載:
public IList<A> GetAItems() { ... }
public IList<B> GetBItems() { ... }
編輯
如果你真的想使用泛型方法,你可以這樣做:
public IList<T> GetItems<T>()
{
return itemsSource.Cast<T>().ToList();
}
但是我不認為為此創建方法有什么意義,而不是將該代碼直接放在您需要特定型別的地方。
編輯 2
看過您的用例后,我真的建議您將CustomListView類設為通用。我知道你說圖書館會阻止這種情況,但有辦法解決這個問題。您已經創建了一個ItemType列舉,您可以CustomListView<T>為每個專案型別創建一個子類:
public class CustomListView<T> : ListView
{
public IList<T> GetItems() => itemsSources.Cast<T>().ToList();
}
public class CustomListViewOfA : CustomListView<A> { }
public class CustomListViewOfB : CustomListView<B> { }
public class UiForClassA
{
public void Foo()
{
var customListView = new CustomListViewOfA();
var itemsOfCustomListView = customListView.GetItems(); //No cast needed
}
}
uj5u.com熱心網友回復:
您希望如何使用這種方法?型別引數由方法的呼叫者設定。無法通過方法設定型別引數。請指定用途。
你可以試試這些:
IList<T> GetItems<T>(ItemType itemType)
{
switch (itemType)
{
case ItemType.A:
return (IList<T>)(IList)(itemsSource.Cast<A>().ToList());
case ItemType.B:
return (IList<T>)(IList)(itemsSource.Cast<B>().ToList());
default:
throw new InvalidOperationException("Not supported");
}
}
IList GetItems(ItemType itemType)
{
switch (itemType)
{
case ItemType.A:
return itemsSource.Cast<A>().ToList();
case ItemType.B:
return itemsSource.Cast<B>().ToList();
default:
throw new InvalidOperationException("Not supported");
}
}
或者,正如@Qwertyluk 在評論中所建議的那樣,如下所示:
private IList<object> GetItems(ItemType itemType)
{
switch (itemType)
{
case ItemType.A:
case ItemType.B:
return itemsSource.Cast<object>().ToList();
default:
throw new InvalidOperationException("Not supported");
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/363415.html
