[英]Suggestions wanted with Lists or Enumerators of T when inheriting from generic classes
我知道答案將不會很簡單,並且我已經使用了一些(我認為很丑陋)的方法。 我只是在尋找一些優雅的答案。
抽象類:
public interface IOtherObjects;
public abstract class MyObjects<T> where T : IOtherObjects
{
...
public List<T> ToList()
{
...
}
}
兒童:
public class MyObjectsA : MyObjects<OtherObjectA> //(where OtherObjectA implements IOtherObjects)
{
}
public class MyObjectsB : MyObjects<OtherObjectB> //(where OtherObjectB implements IOtherObjects)
{
}
是否有可能遍歷MyObjects的集合(或其他類似的組,泛型或其他),然后利用MyObjects基類的ToList方法,因為此時我們還不特別了解T的類型。
編輯對於特定示例,每當出現這種情況時,我都會考慮一會兒,然后做一些不同的事情,因此沒有當前的要求。 但是由於它經常出現,我想我會把它浮動。
EDIT @Sara,它不是我關心的集合的特定類型,它可以是一個List,但每個實例的ToList方法仍然相對不可用,沒有匿名類型)
@aku,是的,這個問題可能是相對假設的,但是能夠知道對象的基本類型將非常有用,但是能夠檢索並處理T個對象的列表。 讓ToList返回BaseType列表是我的解決方法之一
編輯 @全部:到目前為止,這一直是我希望進行的討論,盡管它在很大程度上證實了我的懷疑。 到目前為止,非常感謝所有其他人,隨時輸入。
編輯 @Rob,是的,它適用於已定義的類型,但僅當該類型被稱為IOtherObjects列表時無效。
@Rob 再次感謝。 這通常是我的笨拙變通方法(不要輕視:))。 要么使用ConvertAll函數通過委托向下轉換。 感謝您抽出寶貴的時間來理解問題。
資格編輯 ,以防我有點困惑
更精確地說,(我可能對此的最新實現過於復雜了):
可以說我有兩種對象類型,B和C從對象A繼承。
許多場景都表明了自己的位置,從B列表或C列表,或者在其他情況下從B列表到C列表,但我不知道如果我在基類中是哪個,我需要一個不太具體的列表一種。
上面的示例是“不太具體問題列表”最新化身的簡化示例。
通常,它會自我展示,因為我認為在可能的情況下會限制需要編寫的代碼量,並且看上去比其他選項要優雅一些。 我真的很想討論可能性或其他觀點,這些我或多或少都得到了。 令我驚訝的是,到目前為止,還沒有人提到ConvertAll(),因為這是我使用的另一種解決方法,但是對於手頭的場景來說太冗長了
@羅布再一次和薩拉
謝謝,但是我確實感覺到我在所有靜態上下文榮耀中都了解了泛型,並且確實了解了這里的問題。
我們系統的實際設計及其使用的泛型(我可以說這沒有一點偏見,因為我只是設計中的一員),做得很好。 就是在我使用核心API的時候,我發現有些情況下我在做簡單事情的時候就處於錯誤的境地,相反,我不得不以比我所希望的稍微差一點的優雅來對待它們(嘗試變得聰明一點)或可能很懶-我會接受其中任何一個標簽)。
我不喜歡所謂的“笨拙”,主要是因為我們需要循環遍歷記錄集,僅將對象轉換為其基本值,這可能會降低性能。
我想我想知道以前是否有人在他們的編碼中遇到過這個問題,以及是否有人在處理它時比我聰明,或者至少比我更優雅。
在您的情況下,MyObjectsA和MyObjectsB沒有共同的前身。 通用類是不同類的模板,而不是通用基類。 如果要在不同的類中具有公共屬性,請使用接口。 您不能在循環中調用ToList ,因為它在不同的類中具有不同的簽名。 您可以創建返回對象而不是特定類型的ToList。
為什么會有MyObjects的集合? 您沒有清單是有特定原因的嗎?
您仍然可以訪問ToList()方法,但是由於不確定類型,這樣行不通嗎?
foreach(var myObject in myObjectsList)
foreach(var obj in myObject.ToList())
//do something
當然,這僅適用於C#3.0。
請注意,使用var只是為了消除了解列表包含的類型的要求。 與弗蘭克(Frank)的評論相反,我有一種幻想,即var將使輸入動態化。
好的,我很困惑,下面的代碼對我來說很好(好奇心使我更好!):
// Original Code Snipped for Brevity - See Edit History if Req'd
還是我錯過了什么?
好吧,現在我真的很困惑。您要說的是要從通用/抽象列表中獲取類型化值列表嗎? (因此,子類無關緊要)。
如果類型是子代/接口實現者,則不能返回類型列表-它們不匹配! 您當然可以從抽象List中獲取特定類型的項目的List,如下所示:
public List<OfType> TypedList<OfType>() where OfType : IOtherObjects
{
List<OfType> rtn = new List<OfType>();
foreach (IOtherObjects o in _objects)
{
Type objType = o.GetType();
Type reqType = typeof(OfType);
if (objType == reqType)
rtn.Add((OfType)o);
}
return rtn;
}
如果我仍然不在基地,請您重新輸入您的問題嗎? (似乎我不是唯一一個不確定您在開車的人)。 我正在嘗試確定您是否對仿制葯有誤解。
是的,所以看起來您想要/需要獲取類型化列表的選項,還是基本列表是?
這將使您的抽象類看起來像這樣-您可以使用ToList獲取具體類型,或者使用ToBaseList()獲取接口類型的List。 這應該在您遇到的任何情況下都有效。 有幫助嗎?
public abstract class MyObjects<T> where T : IOtherObjects
{
List<T> _objects = new List<T>();
public List<T> ToList()
{
return _objects;
}
public List<IOtherObjects> ToBaseList()
{
List<IOtherObjects> rtn = new List<IOtherObjects>();
foreach (IOtherObjects o in _objects)
{
rtn.Add(o);
}
return rtn;
}
}
這並不是一個“笨拙”的解決方法(不要輕視),這是唯一的解決方法。我認為這里更大的問題是設計/問題。 您說您有問題,此代碼可以解決。 但是,如果您期望執行以下操作:
public abstract class MyObjects<T> where T : IOtherObjects
{
List<T> _objects = new List<T>();
public List<IOtherObjects> Objects
{ get { return _objects; } }
}
#warning This won't compile, its for demo's sake.
並能夠選擇其中的類型,您還能怎么做? 我感覺到您不太了解泛型的意義,而您正試圖讓它們做一些他們不打算做的事情!
如果你有
class B : A
class C : A
你有
List<B> listB;
List<C> listC;
您希望將其視為父類型的列表
那你應該用
List<A> listA = listB.Cast<A>().Concat(listC.Cast<A>()).ToList()
我最近發現了
List<A>.Cast<B>().ToList<B>()
圖案。
正是我想要的,
泛型用於靜態時間類型檢查, 而不是運行時調度。 使用繼承/接口進行運行時調度,使用泛型進行編譯時類型保證。
interface IMyObjects : IEnumerable<IOtherObjects> {}
abstract class MyObjects<T> : IMyObjects where T : IOtherObjects {}
IEnumerable<IMyObjects> objs = ...;
foreach (IMyObjects mo in objs) {
foreach (IOtherObjects oo in mo) {
Console.WriteLine(oo);
}
}
(顯然,我更喜歡Enumerables而不是List。)
或僅使用適當的動態語言,例如VB。 :-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.