[英]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>
类是IRestriction
和object
。
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.