可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
class MyBase
{
protected object PropertyOfBase { get; set; }
}
class MyType : MyBase
{
void MyMethod(MyBase parameter)
{
// I am looking for:
object p = parameter.PropertyOfBase; // error CS1540: Cannot access protected member 'MyBase.PropertyOfBase' via a qualifier of type 'MyBase'; the qualifier must be of type 'MyType' (or derived from it)
}
}
Is there a way to get a protected property of a parameter of a type from an extending type without reflection? Since the extending class knows of the property through its base type, it would make sense if possible.
回答1:
No, you can't do this.
You're only allowed to access protected members of objects of the accessing type (or derived from it). Here, we don't know whether the parameter is of type MyType or SomeOtherCompletelyDifferentType.
EDIT: The relevant bit of the C# 3.0 spec is section 3.5.3:
When a protected instance member is
accessed outside the program text of
the class in which it is declared, and
when a protected internal instance
member is accessed outside the program
text of the program in which it is
declared, the access must take place
within a class declaration that
derives from the class in which it is
declared. Furthermore, the access is
required to take place through an
instance of that derived class type or
a class type constructed from it. This
restriction prevents one derived class
from accessing protected members of
other derived classes, even when the
members are inherited from the same
base class.
回答2:
Last time I faced a similar problem, I used the solution of adding a protected static method to the base:
class MyBase
{
protected object PropertyOfBase { get; set; }
protected static object GetPropertyOfBaseOf(MyBase obj)
{
return obj.PropertyOfBase;
}
}
class MyType : MyBase
{
void MyMethod(MyBase parameter)
{
object p = GetPropertyOfBaseOf(parameter);
}
}
回答3:
There's a good reason you can't do this. Suppose someone writes:
class Other : MyBase { }
new MyType().MyMethod(new Other());
If the language allowed what you're asking for, you could violate the assumed invariants of Other
by modifying the value of PropertyOfBase
.
回答4:
I think you should ask yourself if there is a better way of doing what you want to do. You want PropertyOfBase to act as public in the context of MyType.MyMethod(), but to be protected in all other situations. Why?
回答5:
A protected property is only accessible to an instance of a derived class, not to instances of derived classes.
There is a difference and it does make sense, protected members should not give up their value to any other instance, even an instance derived from the same type.
(Edited, got myself a bit tongue tied!)
回答6:
As you are inheriting from MyBase, you can access all fields/properties/methods from it marked as "protected" using the "base" keyword.
public class MyBase
{
protected object PropertyOfBase { get; set; }
}
public class MyType : MyBase
{
void MyMethod()
{
object p = base.PropertyOfBase;
}
}
回答7:
You can also declare MyType as a nested class of MyBase (instead of inheriting), this way you can access private/protected members when you send the class MyBase as a parameter
public class MyBase
{
protected object PropertyOfBase { get; set; }
public class MyType
{
public void MyMethod(MyBase parameter)
{
object p = parameter.PropertyOfBase;
}
}
}
To create an instance of MyType just use
var t = new MyBase.MyType();
t.MyMethod(new MyBase());