Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#只能从类内更新的公共字段_C#_Design Patterns_Access Modifiers - Fatal编程技术网

C#只能从类内更新的公共字段

C#只能从类内更新的公共字段,c#,design-patterns,access-modifiers,C#,Design Patterns,Access Modifiers,我有一个C#类,它的字段需要从类外可见,但只能从类内更改。但是,问题是该字段是通过公共mutator方法更新的,而不是直接(或通过属性)更新的: 换句话说,我希望方法Update()只能从FirstClass中访问 几种可能的解决方案以及我不认同它们的原因: 用setter而不是方法更改SecondClass。-不起作用,因为我需要有参数和很多事情要做 将Update()设置为内部而不是公共。-仍然可以从部件内部访问,这还不够好 从第一个类修改第二个类,即将方法Update()移动到第一个类,使

我有一个C#类,它的字段需要从类外可见,但只能从类内更改。但是,问题是该字段是通过公共mutator方法更新的,而不是直接(或通过属性)更新的:

换句话说,我希望方法Update()只能从FirstClass中访问

几种可能的解决方案以及我不认同它们的原因:

  • 用setter而不是方法更改SecondClass。-不起作用,因为我需要有参数和很多事情要做
  • 将Update()设置为内部而不是公共。-仍然可以从部件内部访问,这还不够好
  • 从第一个类修改第二个类,即将方法Update()移动到第一个类,使其私有,并从第二个类公开所有需要的字段。-感觉不是很面向对象
  • 从SecondClass构造函数调用Update(),并在每次需要更新时创建SecondClass的新实例。-性能将受到影响,因为SecondClass中的某些内容永远不会更改,我希望每次调用Update()时都对其进行处理

  • 有办法做到这一点吗?

    一种方法是将名为
    UpdateableSecondClass
    的子类作为第一类的内部类。 它将继承自
    SecondClass
    ,并有一个方法:
    Update()

    您的
    SecondClass
    根本不应该有
    Update()
    方法。你可以继续向世界其他地方展示它:

    public SecondClass TheField {get; private set;}
    

    一种方法是使名为
    UpdateableSecondClass
    的子类成为FirstClass的内部类。 它将继承自
    SecondClass
    ,并有一个方法:
    Update()

    您的
    SecondClass
    根本不应该有
    Update()
    方法。你可以继续向世界其他地方展示它:

    public SecondClass TheField {get; private set;}
    
    来杯咖啡怎么样

    来杯咖啡怎么样


    @aquaraga答案的基本实现,但使用接口:

    public interface ISecond
    {
        // some properties  
    }
    
    public class FirstClass
    {
        private readonly SecondClass _TheField;
        public ISecond TheField { get { return _TheField; } }
    
        public FirstClass()
        {
            _TheField = new SecondClass();
        }
    
        public void SomeMethod()
        {
            // ...
            _TheField.Update(/*parameters*/);
            // ...
        }
    
        private class SecondClass : ISecond
        {
            // some properties  
    
            public void Update(/*parameters*/)
            {       
                // do something
            }
        }
    }
    
    本质上,公开一个公共接口,该接口具有所有可访问的成员,但没有
    Update
    方法。使用一个私有嵌套类,该类具有
    Update
    方法,但调用代码无法访问,并将其作为接口而不是类公开

    一些示例用法:

    FirstClass myFirst = ...
    myFirst.SomeMethod(); //updates ok!
    Console.WriteLine(myFirst.TheField.PropertyA); //can access properties of ISecond
    myFirst.TheField.Update(); //compiler error!
    
    一点是,您提到使用“某些字段”;作为一个接口,您将不能拥有字段,而是属性。我不确定这是否会破坏你的交易

    编辑:您提到了重用
    第二类
    并尽量减少代码重复的意图。一个快速修复方法可能是声明一些
    抽象
    类,一个
    受保护的更新
    方法,使用
    内部
    构造函数(这样其他程序集就不能从中继承),然后用最小的实现公开
    更新
    调用:

    public abstract class SecondClassBase : ISecond
    {
        // some properties
    
        internal SecondClassBase()
        {
    
        }
    
        protected void Update(/*parameters*/)
        {
            // do something
        }
    }
    
    然后,在您的
    第一个类中,除了嵌套类之外,没有任何更改:

    public class FirstClass
    {
        private readonly SecondClass _TheField;
        public ISecond TheField { get { return _TheField; } }
    
        public FirstClass()
        {
            _TheField = new SecondClass();
        }
    
        public void SomeMethod()
        {
            // ...
            _TheField.Update(/*parameters*/);
            // ...
        }
    
        private class SecondClass : SecondClassBase
        {
            public new void Update(/*parameters*/)
            {       
                base.Update(/*parameters*/);
            }
        }
    }
    

    仍然有一些代码重复,但您现在需要做的就是复制/粘贴代码;无需为
    第一类
    的每个实现重新声明属性或
    更新
    逻辑。您还可以将
    新的Update
    方法重命名为其他方法,以避免方法隐藏,但我想我会保留您以前的调用签名。

    是@aquaraga答案的基本实现,但改用接口:

    public interface ISecond
    {
        // some properties  
    }
    
    public class FirstClass
    {
        private readonly SecondClass _TheField;
        public ISecond TheField { get { return _TheField; } }
    
        public FirstClass()
        {
            _TheField = new SecondClass();
        }
    
        public void SomeMethod()
        {
            // ...
            _TheField.Update(/*parameters*/);
            // ...
        }
    
        private class SecondClass : ISecond
        {
            // some properties  
    
            public void Update(/*parameters*/)
            {       
                // do something
            }
        }
    }
    
    本质上,公开一个公共接口,该接口具有所有可访问的成员,但没有
    Update
    方法。使用一个私有嵌套类,该类具有
    Update
    方法,但调用代码无法访问,并将其作为接口而不是类公开

    一些示例用法:

    FirstClass myFirst = ...
    myFirst.SomeMethod(); //updates ok!
    Console.WriteLine(myFirst.TheField.PropertyA); //can access properties of ISecond
    myFirst.TheField.Update(); //compiler error!
    
    一点是,您提到使用“某些字段”;作为一个接口,您将不能拥有字段,而是属性。我不确定这是否会破坏你的交易

    编辑:您提到了重用
    第二类
    并尽量减少代码重复的意图。一个快速修复方法可能是声明一些
    抽象
    类,一个
    受保护的更新
    方法,使用
    内部
    构造函数(这样其他程序集就不能从中继承),然后用最小的实现公开
    更新
    调用:

    public abstract class SecondClassBase : ISecond
    {
        // some properties
    
        internal SecondClassBase()
        {
    
        }
    
        protected void Update(/*parameters*/)
        {
            // do something
        }
    }
    
    然后,在您的
    第一个类中,除了嵌套类之外,没有任何更改:

    public class FirstClass
    {
        private readonly SecondClass _TheField;
        public ISecond TheField { get { return _TheField; } }
    
        public FirstClass()
        {
            _TheField = new SecondClass();
        }
    
        public void SomeMethod()
        {
            // ...
            _TheField.Update(/*parameters*/);
            // ...
        }
    
        private class SecondClass : SecondClassBase
        {
            public new void Update(/*parameters*/)
            {       
                base.Update(/*parameters*/);
            }
        }
    }
    

    仍然有一些代码重复,但您现在需要做的就是复制/粘贴代码;无需为
    第一类
    的每个实现重新声明属性或
    更新
    逻辑。您还可以将
    新的Update
    方法重命名为其他方法,以避免方法隐藏,但我想我会保留与以前相同的调用签名。

    我认为您可以使用以下模式:

    public partial class FirstClass {
        partial class ThirdClass: SecondClass {
            public void PerformUpdate(/* parameters */) {
                base.Update(/* parameters */);
            }
        }
    
        public void SomeMethod() {
        }
    
        public FirstClass() {
        }
    
        public SecondClass TheProperty {
            get {
                return m_TheField;
            }
        }
    
        ThirdClass m_TheField=new ThirdClass();
    }
    
    public partial class SecondClass {
        protected void Update(/* parameters */) {
        }
    
        public SecondClass() {
        }
    }
    
    ThirdClass
    继承自
    SecondClass
    ,但未公开。属性作为类型为
    SecondClass
    的实例公开,但实际上是类型为
    ThirdClass
    的字段


    方法
    SecondClass.Update
    仅对派生类公开。您可以将
    SecondClass
    声明为public,而不是嵌套的,但将文件的更新保持为private

    我认为您可以使用以下模式:

    public partial class FirstClass {
        partial class ThirdClass: SecondClass {
            public void PerformUpdate(/* parameters */) {
                base.Update(/* parameters */);
            }
        }
    
        public void SomeMethod() {
        }
    
        public FirstClass() {
        }
    
        public SecondClass TheProperty {
            get {
                return m_TheField;
            }
        }
    
        ThirdClass m_TheField=new ThirdClass();
    }
    
    public partial class SecondClass {
        protected void Update(/* parameters */) {
        }
    
        public SecondClass() {
        }
    }
    
    ThirdClass
    继承自
    SecondClass
    ,但未公开。属性作为类型为
    SecondClass
    的实例公开,但实际上是类型为
    ThirdClass
    的字段


    方法
    SecondClass.Update
    仅对派生类公开。您可以将
    SecondClass
    声明为public,而不是嵌套的,但将文件的更新保持为private

    克里斯·辛克莱的回答很好,这只是另一个选择

    public sealed class FirstClass : SecondClass
    {
        public FirstClass()
        {
    
        }
    
        public void SomeMethod(int j)
        {
            base.Update(j);
        }
    }
    
    public abstract class SecondClass
    {
    
        public SecondClass() { }
    
        protected void Update(int i)
        {
            Console.WriteLine(i.ToString());
        }
    }
    

    这只是通过FirstClass访问方法的一部分,Chris Sinclair回答很好,这只是另一种选择

    public sealed class FirstClass : SecondClass
    {
        public FirstClass()
        {
    
        }
    
        public void SomeMethod(int j)
        {
            base.Update(j);
        }
    }
    
    public abstract class SecondClass
    {
    
        public SecondClass() { }
    
        protected void Update(int i)
        {
            Console.WriteLine(i.ToString());
        }
    }
    
    这只是获取冰毒的一部分