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

时间:2014-01-18 10:43:23

标签: c# .net 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);

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

3 个答案:

答案 0 :(得分:21)

您的方法很典型(例如,IEnumerable&lt; T&gt;像这样实现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; }
}

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

答案 1 :(得分: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;
        }
    }
}

这样,当您不关心它的类型时,您可以在所有Limitobject IRestriction访问foreach(IRestriction restriction in this.Restrictions) { Console.WriteLine(restriction.Limit); } 。例如:

{{1}}

答案 2 :(得分:0)

接口是实现合同的实体需要遵循的合同。

您已创建两个名称为IRestriction

的合约

据我所知,你基本上可能需要的是一个可以限制的类的标志,它应该实现IRestriction非通用接口。

第二个接口似乎是也包含limit属性的可限制对象。 因此,第二个IRestriction接口的定义可以是ILimitRestriction或任何适合您业务需求的名称。

因此ILimitRestriction可以继承自IRestriction,这会标记继承ILimitRestriction

IRestriction个对象的类
public abstract class AbstractBlockRule
{
    public long Id{get;set;}
    public abstract List<IRestriction> Restrictions {get;};
}

public interface IRestriction{}

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

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

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

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