受保护的泛型类 - 是否支持?

时间:2014-02-20 18:01:39

标签: c# class generics abstract protected

我对C#泛型有疑问。我希望在我的抽象类中存储泛型类型变量,而不在类外声明该类型。

以下是代码示例。请注意,我不希望将 Param 类暴露在 Calc 类之外。

提前致谢。 - Dutta。

abstract class Base { }

abstract class Calc<T> where T : Base
{
    protected Param Member; /* how can this be a made a generic declaration 
                             * WITHOUT declaring this class like,
                             * class Calc<T, P> 
                             *      where T : Base
                             *      where P : Param */

    protected Calc(Param p)
    {
        this.Member = p;
    }

    protected abstract class Param { }
}

class MyBase : Base { }

class MyCalc : Calc<MyBase>
{
    public MyCalc() : base(new MyParam()) { }

    public void doSomething()
    {
        base.Member.A++; // fails on compilation
    }

    private class MyParam : Calc<MyBase>.Param
    {
        public int A;

        public MyParam() { this.A = 0; }
    }
}

2 个答案:

答案 0 :(得分:1)

你只需要将它转换为新类型,因为无论如何,变量Member被声明为Param并且它将始终作为Param访问:

((MyParam)base.Member).A++; 

其次,您可以通过更改以下内容来修复MyParam类:

MyParam : Calc<MyBase>.Param

对此:

MyParam : Param

因为Param已经通过泛型和继承Calc<MyBase>了。

答案 1 :(得分:0)

Thraka的回答是正确的:如果你不想使用泛型,你需要施放。只是添加它,以防你真正想要做的事情看起来像这样。这是一组可以从库中公开的类,它们不会被客户端扩展(除非它们以完全信任的方式运行并且可以使用反射等。!!)但是可以以类型安全的方式使用。

public abstract class SupportedPaymentMethod
{
    protected internal SupportedPaymentMethod() { }
}

public sealed class Check : SupportedPaymentMethod
{
    public int CheckNumber { get; private set; }

    public Check(int checkNumber)
     : base()
    {
        CheckNumber = checkNumber;
    }
}

public sealed class CreditCard : SupportedPaymentMethod
{
    public CreditCard()
     : base()
    { }
}

public abstract class Payment<T>
    where T : SupportedPaymentMethod
{
    public T Method { get; private set; }

    protected internal Payment(T method)
    {
        Method = method;
    }
}

public sealed CheckPayment : Payment<Check>
{
    public CheckPayment(Check check)
     : base(check)
    { }
}

public sealed CreditCardPayment : Payment<CreditCard>
{
    public CreditCardPayment(CreditCard creditCard)
     : base(creditCard)
    { }
}

客户端(即类库的程序集之外的代码)将能够实例化CheckPaymentCreditCardPayment,但是他们将无法创建源自{{1}的新类}。因此,例如,客户端无法创建Payment<T>。 :)

拨打CheatingPaymentMethod : Payment<Cheating>之类的电话现在可以正常工作:

base.Member.A++
相关问题