继承Non-Generic One C#的通用接口

cal*_*rgs 23 .net c# oop generics

这是课堂设计问题.

我有主要的抽象类

public abstract class AbstractBlockRule
{
    public long Id{get;set;}
    public abstract List<IRestriction> Restrictions {get;};
}

public interface IRestriction{}

public interface IRestriction<T>:IRestriction where T:struct
{
    T Limit {get;} 
}

public TimeRestriction:IRestriction<TimeSpan>
{
    public TimeSpan Limit{get;set;}
}

public AgeRestriction:IRestriction<int>
{
    public int Limit{get;set;}
}

public class BlockRule:AbstractBlockRule
{
    public virtual List<IRestriction> Restrictions {get;set;}
}

BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();

rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
Run Code Online (Sandbox Code Playgroud)

我必须使用非泛型接口IR限制,以避免在主抽象类中指定泛型类型T. 我对仿制药很新.有人可以让我知道如何更好地设计这个东西吗?

Jac*_*ack 23

您的方法很典型(例如,IEnumerable <T>像这样实现IEnumerable).如果要为代码的使用者提供最大效用,那么在非泛型接口上提供非泛型访问器,然后将其隐藏在通用实现中会很好.例如:

public abstract class AbstractBlockRule
{
    public long Id{get;set;}
    public abstract List<IRestriction> Restrictions { get; set; }
}

public interface IRestriction
{
    object Limit { get; }
}

public interface IRestriction<T> : IRestriction 
    where T:struct
{
    // hide IRestriction.Limit
    new T Limit {get;} 
}

public abstract class RestrictionBase<T> : IRestriction<T>
    where T:struct
{
    // explicit implementation
    object IRestriction.Limit
    {
        get { return Limit; }
    }

    // override when required
    public virtual T Limit { get; set; }
}

public class TimeRestriction : RestrictionBase<TimeSpan>
{
}

public class AgeRestriction : RestrictionBase<TimeSpan>
{
}

public class BlockRule : AbstractBlockRule
{
    public override List<IRestriction> Restrictions { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我还在这里展示了使用基本限制类​​,但这不是必需的.


Dan*_*ker 5

运行时将IRestriction<TimeSpan>IRestriction<int>视为不同的不同类(它们甚至具有自己的一组静态变量)。在您的情况下,IRestriction<TimeSpan>IRestriction<int>继承层次结构中唯一通用的类是IRestrictionobject

因此,确实,列出清单IRestriction是唯一明智的方法。


附带说明:Limit无论您使用的是IRestriction<TimeSpan>还是,都可以在其中拥有一个属性IRestriction<int>。我会做什么在这种情况下是定义另一个属性object Limit { get; }IRestriction,并把它藏在实际执行。像这样:

public interface IRestriction
{
    object Limit { get; }
}

public interface IRestriction<T> : IRestriction
    where T : struct
{
    new T Limit { get; set; }
}

public class TimeRestriction : IRestriction<TimeSpan>
{
    public TimeSpan Limit { get; set; }

    // Explicit interface member:
    // This is hidden from IntelliSense
    // unless you cast to IRestriction.
    object IRestriction.Limit
    {
        get
        {
            // Note: boxing happens here.
            return (object)Limit;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,当您不在乎它是什么类型时,就可以Limit像访问object所有内容一样访问IRestriction。例如:

foreach(IRestriction restriction in this.Restrictions)
{
    Console.WriteLine(restriction.Limit);
}
Run Code Online (Sandbox Code Playgroud)