簡體   English   中英

創建一個List實例,其類型派生自基類和接口

[英]Create an instance of a List where the type derives from a base class and an interface

我有一個類,該類將存儲從基類派生並實現接口的對象。 在此示例中,所有類型都派生自UIElement並實現我的接口IDropTarget

所以在我的課堂上,我可以用一種奇妙的方式使用泛型類型推斷來要求它,而不必將所有內容都限制在特定的基類中

public void AddDropTarget<TTarget>(TTarget target)
    where TTarget : UIElement, IDropTarget
{
    target.DoSomethingAsUIElement();
    target.DoSomethingAsIDropTraget();

    // Now I want to save it for another method
    list.Add(target);
}

public void DoStuff()
{
    foreach(var item in list)
    {
        item.MoreUIElementAndDropStuff();
    }
}

不幸的是,我似乎沒有辦法存儲此TTarget受限列表。 我不能將其限制為特定的類型,因為我已經有多個類從UIElement派生(矩形,按鈕,網格等),而且我沒有辦法使所有這些對象都從基本類型派生。

我的下一個解決方案是存儲每種類型的列表。 我需要弄清楚這些開銷是否值得,而不是每次使用它們時都要投射對象。

您不能通過這種方式將兩種不同的類型添加到列表中。 你基本上是說,你想他們一般類型設置為XY 想象一下,當您進行一次foreach時會發生什么,編譯器將不知道您是否需要UIElementIDragDrop

您只需要手動維護類型安全。 使用私有列表(我想就像您正在做的那樣),然后手動進行投射。 取決於您要使用哪種類型或任何類型。

public class MyClass {

    private _list = new List<object>();  // don't store any type info for now

    public void AddDropTarget.... /* this is already correct */

    public void RunUiStuff() {
        // get all items that are of type UIElement.  Items of wrong type will be ignored
        foreach(var e in _list.OfType<UIElement>()) {

        }
    }

    public void RunDropStuff() {
        // cast works as well, but will throw if any object is not the correct type
        foreach(var e in _list.Cast<IDropTarget>()) {
        }
    }
}

如果您不想強制轉換,則可以使用裝飾器模式的變體來創建所需的公共基類。

//our new base type
public interface IElementAndDropTarget : IDropTarget
{
    void DoSomethingAsUIElement();
    void MoreUIElementAndDropStuff();
}

// our decorator. We need to store UIElement and IDropTarget
// as different fields. The static "Make" is giving you
// the compile-time guarantee that they both refer
// to the same class
public class UIElementDecorator : IElementAndDropTarget
{
    private readonly UIElement t;
    private readonly IDropTarget dt;

    private UIElementDecorator(UIElement t, IDropTarget dt)
    {   
        this.t=t;
        this.dt=dt;
    }

    public static UIElementDecorator Make<T>(T t) where T: UIElement, IDropTarget
    {
        return new UIElementDecorator(t,t);
    }

    public void DoSomethingAsUIElement() {t.DoSomethingAsUIElement();}
    public void MoreUIElementAndDropStuff(){t.MoreUIElementAndDropStuff();}
    public void DoSomethingAsIDropTarget() {dt.DoSomethingAsIDropTarget();}
}

這樣,您的列表可以是

public List<IElementAndDropTarget> list = new List<IElementAndDropTarget>(); 

AddDropTarget ,可以使用修飾的類將其填充為:

list.Add(UIElementDecorator.Make(target));

就是這樣。 您的其余代碼可以保持不變。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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