Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 继承非泛型C的泛型接口#_C#_.net_Oop_Generics - Fatal编程技术网

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

C# 继承非泛型C的泛型接口#,c#,.net,oop,generics,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

这是课堂设计问题

我有一个主要的抽象类

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);
公共抽象类AbstractBlockRule
{
公共长Id{get;set;}
公共摘要列表限制{get;};
}
公共接口i限制{}
公共接口IRestriction:IRestriction,其中T:struct
{
T限制{get;}
}
公共时间限制:i限制
{
公共时间跨度限制{get;set;}
}
公共行政限制:直接限制
{
公共整数限制{get;set;}
}
公共类BlockRule:AbstractBlockRule
{
公共虚拟列表限制{get;set;}
}
BlockRule规则=新的BlockRule();
时间限制t=新的时间限制();
AgeRestriction a=新的AgeRestriction();
规则。限制。添加(t);
规则.限制.加入(a);
我必须使用非泛型接口IRestriction,以避免在主抽象类中指定泛型类型T。我对泛型很陌生。有人能告诉我如何更好地设计这个东西吗?

您的方法是典型的(例如,IEnumerable实现了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; }
}
foreach(IRestriction restriction in this.Restrictions)
{
    Console.WriteLine(restriction.Limit);
}
公共抽象类AbstractBlockRule
{
公共长Id{get;set;}
公共抽象列表限制{get;set;}
}
公共接口限制
{
对象限制{get;}
}
公共接口IRestriction:IRestriction
其中T:struct
{
//隐藏限制。限制
新的T限制{get;}
}
公共抽象类限制库:IRestriction
其中T:struct
{
//显式实现
对象限制。限制
{
获取{返回限制;}
}
//在需要时覆盖
公共虚拟T限制{get;set;}
}
公共类时间限制:RestrictionBase
{
}
公共类限制:限制基
{
}
公共类BlockRule:AbstractBlockRule
{
公共覆盖列表限制{get;set;}
}

这里我还演示了如何使用一个基本限制类,但它不是必需的。

接口是需要由实现该协定的实体遵循的协定

您已经创建了两个同名的合同
i限制

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;}
}
就我所见,您基本上可能需要的是一个可以被限制的类的标志,它应该实现
IRestriction
非泛型接口

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

因此,
ILimitRestriction
可以从
IRestriction
继承,这将标记继承
ILimitRestriction
的类

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;}
}
公共抽象类AbstractBlockRule
{
公共长Id{get;set;}
公共摘要列表限制{get;};
}
公共接口i限制{}
公共接口IRestrictionWithLimit:IRestriction其中T:struct
{
T限制{get;}
}
公共时间限制:IRestrictionWithLimit
{
公共时间跨度限制{get;set;}
}
公共管理限制:有限制的直接限制
{
公共整数限制{get;set;}
}
公共类BlockRule:AbstractBlockRule
{
公共虚拟列表限制{get;set;}
}

运行时将
IRestriction
IRestriction
视为不同的类(它们甚至有自己的静态变量集)。在您的情况下,继承层次结构中的
irestruction
irestruction
共同的类只有
irestruction
object

因此,拥有一个
i限制列表是唯一明智的选择


作为旁注:您在其中有一个属性
Limit
,无论您是处理
IRestriction
还是
IRestriction
,您都可能希望访问该属性。在这种情况下,我将在
IRestriction
上定义另一个属性
对象限制{get;}
,并将其隐藏在实际实现中。像这样:

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

对我来说,很难改进你的代码。如果需要,非泛型基接口可以有一个属性
ValueType-BoxedLimit{get;}
,但我不确定它是否有用。毕竟,为什么您需要不同类型对象的
列表
(当然,当您将通用接口与值类型(结构)一起使用时,使其协变的明显想法,
IRestriction
,是没有用的,因为C#和.NET不支持值类型的协变。)我不知道为什么不将抽象类或方法设置为泛型。
限制是最小值还是最大值?如果是这样的话,
IComparable
可能会更有用。