簡體   English   中英

從泛型類繼承時需要T的列表或枚舉器的建議

[英]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

還是我錯過了什么?

根據OP更新響應

好吧,現在我真的很困惑。您要說的是要從通用/抽象列表中獲取類型化值列表嗎? (因此,子類無關緊要)。

如果類型是子代/接口實現者,則不能返回類型列表-它們不匹配! 您當然可以從抽象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;
    }

如果我仍然不在基地,請您重新輸入您的問題嗎? (似乎我不是唯一一個不確定您在開車的人)。 我正在嘗試確定您是否對仿制葯有誤解。

另一個更新:D

是的,所以看起來您想要/需要獲取類型化列表的選項,還是基本列表是?

這將使您的抽象類看起來像這樣-您可以使用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;
    }
}

更新#3

這並不是一個“笨拙”的解決方法(不要輕視),這是唯一的解決方法。我認為這里更大的問題是設計/問題。 您說您有問題,此代碼可以解決。 但是,如果您期望執行以下操作:

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.

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