我正在将一个VB.NET项目转换为C#。有一个代码块在转换时,有一个调用超类中受保护构造函数的方法。我在这里做了一个最小的例子:
public class A
{
protected A() { }
}
public class B : A
{
static A MakeA() {
return new A();
}
}
在new A()
上,我看到"CS0122:A. A()因其保护级别而无法访问"。
现在,这对我来说是一个问题,因为类A
在一个我无法控制的库中,我们的VB.NET代码调用这个构造函数没有问题,但C#有问题。
为什么会有这种事?
我能做些什么呢?
2条答案
按热度按时间zpf6vheq1#
这在C#规范(ECMA-334)中被调用,并给出了原因 (我的粗体)
7.5.4受保护的访问
当
protected
或private protected
示例成员在声明它的类的程序文本之外被访问时,以及当protected internal
示例成员在声明它的程序的程序文本之外被访问时,访问应在从声明它的类派生的类声明内发生。此外,访问必须通过该派生类类型的示例或从其构造的类类型来进行。2此限制防止一个派生类访问其他派生类的受保护成员,即使这些成员是从同一基类继承的。虽然它对构造函数没有太大的影响,但是它对常规方法有很大的影响。
你必须使用你自己的类型的示例来做这件事,所以
MeowCat
是允许的,但WagDogsTail
不行。因此构造函数只能通过你自己的派生类的示例来调用,所以你不能直接使用new()
来调用它,只能从另一个构造函数中使用base()
。在ECMA-335(.NET规范)中也提到了这一点:
8.5.3.2成员和嵌套类型的可访问性
family-支持相同类型的引用对象可以访问(例如,一个确切的类型和从它继承的所有类型)对于可验证的代码(参见§8.8),还有一个额外的要求,可能需要运行时检查:**引用应该通过一个其确切类型支持被引用者确切类型的项来进行。**也就是说,其成员正在被访问的项应该从执行访问的类型继承。
wb1gzix02#
你需要理解为什么基类要使用一个受保护的构造函数。它可能会提供某种工厂方法来创建基类的示例,你应该使用它。
通过简单地返回派生类的一个示例,在派生类中可以在某种程度上颠覆这一点:
这可能是一个非常糟糕的主意。
想象一下,如果
A
的实现依赖于一些特殊的代码,这些代码在受保护的构造函数完成之后初始化A
的一些字段,例如:有了这两个类,代码就可以做到这一点:
结果很糟糕。
因此,您必须找出
A
的示例是如何正确创建的,然后使用它。