使派生类中的只读属性可写

我想要实现的目标如下:我在BaseClass中声明了一个属性。 如果通过基类’指针访问此属性,则只有getter可用,但如果使用派生类指针,我希望能够获取并设置该属性。 所以intellisense甚至不应该显示基本指针的setter。

public class BaseClass { public virtual int MyProperty { get { return 1; } set {;}//This would show the setter in Intellisense } } public class DerivedClass : BaseClass { int intValue; public override int MyProperty { set { intValue = value;} } } 

一个现实的例子
考虑一种情况,其中您有一个从Person类派生的Parent和Child类。 想象一下属性-RestrictionLevel,两者都可以读取它,但只有父级可以设置值。 有没有更好的方法来设计这种情况?

我能想到的唯一方法就是用新的方式遮蔽房产:

 public class DerivedClass : BaseClass { int intValue; public new int MyProperty { get { return intValue; } set { intValue = value; } } } 

注意如何将属性声明为new而不是override 。 当然,这意味着DerivedClass类型的MyPropertyBaseClass类型的MyProperty无关,它是一个全新的属性,恰好具有相同的名称(因此将其隐藏在基类中)。

结果如下:

 DerivedClass d = new DerivedClass(); d.MyProperty = 42; BaseClass b = new DerivedClass(); b.MyProperty = 42; /* compilation error: Property or indexer 'TheNamespace.BaseClass.MyProperty' cannot be assigned to -- it is read only */ 

另外,正如@silky在评论中所述:

(虽然我建议你做,而父母,请参考相同的变量,以避免一个非常令人困惑的情况)但我真的不认为这是适当的。

…您可能希望新属性访问基类中的属性(通过base.MyProperty ,使用受保护的setter完成)。 例如,请考虑以下事项:

 DerivedClass d = new DerivedClass(); d.MyProperty = 42; BaseClass b = d; Console.WriteLine(b.MyProperty); // prints 1 

也就是说,使用new时我总觉得有点脏(当我想到它时,我不确定我是否真的在生产代码中完成了)。

更新
给定您给出的示例场景(我以一种方式解释Parent是否能够设置子级的RestrictionLevel ),它可以像这样解决:

 public enum RestrictionLevel { Low, Medium, Grounded } public class Person { public RestrictionLevel RestrictionLevel { get; private set; } protected static void SetRestrictionLevelInternal(Person person, RestrictionLevel restrictionLevel) { person.RestrictionLevel = restrictionLevel; } } public class Child : Person { } public class Parent : Person { public void SetRestrictionLevel(Child child, RestrictionLevel restrictionLevel) { SetRestrictionLevelInternal(child, restrictionLevel); } } 

这意味着以下代码有效:

 Child c = new Child(); Parent p = new Parent(); p.SetRestrictionLevel(c, RestrictionLevel.Grounded); 

……但这个不是:

 Child c = new Child(); c.SetRestrictionLevel(c, RestrictionLevel.Low); 

方法SetRestrictionLevelInternal可以从任何后代类型(包括Child )中调用,但不能从类型本身外部调用。 因此,您无法在Parent实例上调用SetRestrictionLevelInternal 。 在上面的示例中,我们选择公开一个public方法,该方法又调用protected方法。

编程到接口,而不是实现:

 public interface IFoo { int MyProp { get; } } public interface IFooWithSetter { int MyProp { get; set; } } public class FooImplementation : IFoo, IFooWithSetter { public int MyProp { get { return 100; } set { } } } 

使用范例:

 IFoo var1 = new FooImplementation(); // only getter is available in var1 IFooWithSetter var2 = (IFooWithSetter) var1; // setter and getter is available in var2 

您可以轻松地将一些私有修饰符用于具有不同合同的接口。 这个解决方案很简单,IMO套件适合您的任务。
如果你认为做一些你想隐藏/限制的行动很容易,那你就是对的。 任何可能的方式也是如此。

这是不可能的(AFAIK)。 无论如何,这会让人感到困惑。 您想要这样做的任何特殊原因?