首页 文章

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

提问于
浏览
1

我在C#基类上有一个枚举属性,我想在所有派生类上实现只读,除了一个(我需要在其上读写该属性) .

我的枚举声明如下:

enum Visibility { Public, Shared, Private }

(顺便说一句,枚举成员名称与C#可见性修饰符无关!)

最初我以为我能够在基类上声明属性,如下所示:

abstract class DataViewBase
{
    public Visibility Visibility { get; protected set; }
}

然后更改派生类的声明:

sealed class FooDataView : DataViewBase
{
    public Visibility Visibility { get; set; }
}

从而使setter公开,但我应该意识到这隐藏了基础 Visibility 属性并生成编译器警告 . 添加 new 关键字(即.2778871_)可以消除警告,但 FooDataView 上的属性实际上变成了一个全新的属性,与基类上的属性没有任何关联 . 因此,如果我这样做:

var foo = new FooDataView();
    foo.Visibility = Visibility.Shared;
    Console.WriteLine(foo.Visibility);  // Shared
    var casted = (DataViewBase) foo;
    Console.WriteLine(casted.Visibility);  // Public

两个 Visibility 属性值不同,这不是我想要的 .

我最终通过声明属性来解决这个问题:

sealed class FooDataView : DataViewBase
{
    public new Visibility Visibility
    {
        get { return base.Visibility; }
        set { base.Visibility = value; }
    }
}

这可确保保留两个 Visibility 属性"in-sync" .

然而,在完成所有这些之后,我想知道是否有另一种方法来完成我想要的东西(根据问题 Headers ),因为我的解决方案似乎有点不优雅 . 我想不出任何其他明显的解决方案 .

3 回答

  • 1

    这两个怎么样:

    1. Add A New Method

    class FooDataView : DataViewBase
    {
        public void ChangeVisibility(Visibility visibility)
        {
            Visibility = visibility;
        }
    }
    

    只需添加一个新的 ChangeVisibility() 方法 . 我认为这是最简单的 .

    2. Use Interface:

    public interface IDataView
    {
        Visibility Visibility { get; }
    }
    
    public class DataView : IDataView
    {
        public Visibility Visibility { get; set; }
    }
    
    public class PrivateDataView : IDataView
    {
        public Visibility Visibility
        {
            get { return Visibility.Private; }
        }
    }
    

    我个人更喜欢第一种方法 .

  • 1

    然而,在完成所有这些之后,我想知道是否有另一种方法来完成我想要的东西(根据问题 Headers ),因为我的解决方案似乎有些不优雅 . 我想不出任何其他明显的解决方案 .

    不,没有其他解决方案 . 为什么要将属性更改为可在派生类中公开设置(似乎setter在基类中也应该是公共的)?也许您应该以其他方式公开此功能 .

  • 1

    您可以创建一个访问setter的接口:

    interface ISetVisibility {
        Visibility Visibilty {set;}
    }
    
    class MyDerived : MyBase, ISetVisibility {
        Visibility ISetVisibilty.Visibility { set {/* ... */ } }
    }
    

    现在在您的主类中,您可以使用以下内容:

    ((ISetVisibility) myDerived).Visibility = Visibilty.Shared;
    

相关问题