受保护的泛型类 - 是不是支持?
Posted
技术标签:
【中文标题】受保护的泛型类 - 是不是支持?【英文标题】:Protected generic class - is it supported?受保护的泛型类 - 是否支持? 【发布时间】:2014-03-21 21:00:56 【问题描述】:我有一个关于 C# 泛型的问题。我希望在我的抽象类中存储一个泛型类型变量,而不在类之外声明该类型。
以下是代码示例。请注意,我不希望将 Param 类暴露在 Calc 类之外。
提前致谢。 - 杜塔。
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;
【问题讨论】:
你为什么想要一个受保护的类?你想完成/预防什么?什么不工作?你有什么看起来不错 我需要一个受保护的 Param 类,因为我只希望从 Calc 派生的类能够实例化和调用它的方法。 这与说您不希望Param
泛型类型参数为“public”不同。
是的,我不想公开。
我的回答对你有用吗?如果是这样,请将其标记为这样。如果没有,请告诉我们原因。谢谢!
【参考方案1】:
你只需要把它转换成新的类型,因为无论如何,变量 Member 被声明为 Param 并且它总是作为 Param 被访问:
((MyParam)base.Member).A++;
其次,您可以通过以下更改来修复您的 MyParam 类:
MyParam : Calc<MyBase>.Param
到这里:
MyParam : Param
因为通过泛型和继承,Param 已经是Calc<MyBase>
。
【讨论】:
非常正确——我是这样写的,所以要明确代码。我在该行没有编译错误。 我没有注意到您指出了错误所在。我已经更新了答案以反映我认为您需要做的事情。 Thraka 的更新答案是正确的。只要您不使用泛型,强制转换是必要的。无论如何,用于泛型类型参数的类型必须与泛型类本身具有相同的可见性 - 在您的情况下,与从类中公开参数的方式相同。 虽然选角是我想尽可能避免的事情,但我不能否认这确实是一个前进的方向。感谢 Thraka 和 Lars 试图回答这个问题。我已将此标记为正确答案。【参考方案2】: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)
客户端(即类库程序集之外的代码)将能够实例化 CheckPayment
或 CreditCardPayment
,但他们将无法创建派生自 Payment<T>
的新类。因此,例如,客户端无法创建CheatingPaymentMethod : Payment<Cheating>
。 :)
像您对 base.Member.A++
的预期调用一样的调用现在可以工作了:
var checkPayment = new CheckPayment(new Check(123456));
var checkNumber = checkPayment.Method.CheckNumber; // Success! :)
【讨论】:
以上是关于受保护的泛型类 - 是不是支持?的主要内容,如果未能解决你的问题,请参考以下文章