开发者

Casting and interface inheritance

Each item has an interface, IItem. As well as this, there is a interface known as IDrawableItem which inherits from Item.

The code below, is trying to draw a drawable item, but cannot as the collection this class stores accepts only IItem. You can add anything that inherits from IItem to this class, but using other methods can only be achieved by casting.

foreach (var item in Items) {
    item.Draw();               // The casting would go here.
}

I know how to cast, as etc... but is this accept开发者_如何学Goable? Is it a best practice?

Just wondering if there are other ways to handle such scenarios.


Use Enumerable.OfType to extract only those elements of Items that implement IDrawableItem:

foreach(var item in Items.OfType<IDrawableItem>()) {
    item.Draw();
}

To address the question that Nanook asked in the comments the above code will probably be translated into code equivalent to the following:

foreach(var item in Items) {
     if(item is IDrawableItem) {
        ((IDrawable)item).Draw();
     }
}

Of course, really there is an iterator behind the scenes that looks something like this:

public static IEnumerable<T> OfType<T>(this IEnumerable<TSource> source) {
    if(source == null) {
        throw new ArgumentNullException("source");
    }
    foreach(TSource item in source) {
        if(item is T) {
            yield return (T)item;
        }
    }
}

So, what this shows is that we probably only iterate through Items once. Of course, there is no requirement that OfType is implemented like the above but this is the sensible thing to do.


Two alternative solutions:

  • Keep the drawables in a separate collection.
  • Add DrawIfPossible() method to IItem. IDrawableItem should override it to call Draw(), other IItem() implementors should have an empty implementation.

Explicit type querying is considered a sign that there might be something wrong with the design.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜