Затенение унаследованных элементов универсального интерфейса в .NET: хорошо, плохо или некрасиво?

Я знаю, что затенение членов в реализациях классов может привести к ситуациям, когда "неправильный" член может быть вызван в зависимости от того, как я привел мои экземпляры, но с интерфейсами я не вижу, что это может быть проблемой, и я довольно часто пишу такие интерфейсы:

public interface INode
{
    IEnumerable<INode> Children { get; }
}

public interface INode<N> : INode
    where N : INode<N>
{
    new IEnumerable<N> Children { get; }
}

public interface IAlpha : INode<IAlpha>
{ }

public interface IBeta : INode<IBeta>
{ }

В моем коде есть места, которые знают только о INode , поэтому дети также должен иметь тип INode .

В других местах, где я хочу знать о конкретных типах - в реализации моего примера интерфейсов IAlpha и IBeta Я хочу, чтобы типы детей были такими же, как у их родителей.

Поэтому я реализую класс NodeBase l Примерно так:

public abstract class NodeBase<N> : INode<N>
    where N : INode<N>
{
    protected readonly List<N> _children = new List<N>();

    public IEnumerable<N> Children
    {
        get { return _children.AsEnumerable(); }
    }

    IEnumerable<INode> INode.Children
    {
        get { return this.Children.Cast<INode>(); }
    }
}

В реальной реализации нет затенения, только в интерфейсах.

Конкретные экземпляры IAlpha и IBeta выглядят следующим образом:

public class Alpha : NodeBase<Alpha>, IAlpha
{
    IEnumerable<IAlpha> INode<IAlpha>.Children
    {
        get { return this.Children.Cast<IAlpha>(); }
    }
}

public class Beta : NodeBase<Beta>, IBeta
{
    IEnumerable<IBeta> INode<IBeta>.Children
    {
        get { return this.Children.Cast<IBeta>(); }
    }
}

Опять же, нет затенения в реализациях.

Теперь я могу получить доступ к этим типам следующим образом:

var alpha = new Alpha();
var beta = new Beta();

var alphaAsIAlpha = alpha as IAlpha;
var betaAsIBeta = beta as IBeta;

var alphaAsINode = alpha as INode;
var betaAsINode = beta as INode;

var alphaAsINodeAlpha = alpha as INode<Alpha>;
var betaAsINodeBeta = beta as INode<Beta>;

var alphaAsINodeIAlpha = alpha as INode<IAlpha>;
var betaAsINodeIBeta = beta as INode<IBeta>;

var alphaAsNodeBaseAlpha = alpha as NodeBase<Alpha>;
var betaAsNodeBaseBeta = beta as NodeBase<Beta>;

Каждая из этих переменных теперь имеет правильную строго типизированную коллекцию Children .

Итак, мои вопросы просты. Является ли затенение элементов интерфейса с помощью такого шаблона хорошим, плохим или уродливым? И почему?

9
задан Enigmativity 12 August 2011 в 05:04
поделиться