简体   繁体   English

继承非泛型一 C# 的泛型接口

[英]Generic Interface inheriting Non-Generic One C#

This is class design question.这是班级设计问题。

I have main abstract class我有主要的抽象类

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);

I have to use non-generic Interface IRestriction just to avoid specifying generic type T in main abstract class.我必须使用非泛型接口 IRestriction 来避免在主抽象类中指定泛型类型 T。 I'm very new to generics.我对泛型很陌生。 Can some one let me know how to better design this thing?有人可以让我知道如何更好地设计这个东西吗?

Your approach is typical (for example, IEnumerable<T> implements IEnumerable like this).您的方法是典型的(例如, IEnumerable<T> 像这样实现 IEnumerable )。 If you want to provide maximum utility to consumers of your code, it would be nice to provide a non-generic accessor on the non-generic interface, then hide it in the generic implementation.如果您想为代码的使用者提供最大的效用,最好在非泛型接口上提供非泛型访问器,然后将其隐藏在泛型实现中。 For example:例如:

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; }
}

I also showed using a base restriction class here, but it is not required.我还在此处展示了使用基本限制类​​,但这不是必需的。

The runtime treats IRestriction<TimeSpan> and IRestriction<int> as different distinct classes (they even have their own set of static variables).运行时将IRestriction<TimeSpan>IRestriction<int>视为不同的不同类(它们甚至有自己的一组静态变量)。 In your case the only classes common to both IRestriction<TimeSpan> and IRestriction<int> in the inheritance hierarchy are IRestriction and object .在您的情况下,继承层次结构中IRestriction IRestriction<TimeSpan>IRestriction<int>唯一IRestriction<TimeSpan>类是IRestrictionobject

So indeed, having a list of IRestriction is the only sensible way to go.因此,确实,拥有IRestriction列表是唯一明智的方法。


As a side note: you have a property Limit in there that you might want to access regardless of whether you're dealing with an IRestriction<TimeSpan> or IRestriction<int> .附带说明:您在那里有一个属性Limit ,无论您是在处理IRestriction<TimeSpan>还是IRestriction<int> ,您都可能想要访问它。 What I would do in this case is to define another property object Limit { get; }在这种情况下我会做的是定义另一个属性object Limit { get; } object Limit { get; } on IRestriction , and hide it in the actual implementation. object Limit { get; }IRestriction ,并把它藏在实际执行。 Like this:像这样:

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;
        }
    }
}

This way you can access Limit as object on all your IRestriction when you don't care what type it is.这样,当您不关心它是什么类型时,您可以在所有IRestriction Limit作为object访问。 For example:例如:

foreach(IRestriction restriction in this.Restrictions)
{
    Console.WriteLine(restriction.Limit);
}

Interfaces are contracts that need to be followed by the entity that implements the contract.接口是实现合约的实体需要遵循的合约。

You have created two contract with the same name IRestriction您已经创建了两个同名的合约IRestriction

As far as I can see, what you are basically may need is a flag for classes that can be restricted, which should implement the IRestriction non-generic interface.据我所知,您基本上可能需要一个可以限制类的标志,它应该实现IRestriction非通用接口。

The second interface seems to be restrictable objects that also contain a limit property.第二个接口似乎是也包含限制属性的受限制对象。 Hence the definition of the second IRestriction interface can be ILimitRestriction or whatever name suits your business needs.因此,第二个IRestriction接口的定义可以是ILimitRestriction或任何适合您业务需求的名称。

Hence ILimitRestriction can inherit from IRestriction which would mark classes inheriting ILimitRestriction still objects of IRestriction因此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;}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM