Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.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#_Access Modifiers - Fatal编程技术网

C# 类只能由“写入”;“家长”;类,但可被其他类读取

C# 类只能由“写入”;“家长”;类,但可被其他类读取,c#,access-modifiers,C#,Access Modifiers,我使用的是C#,我没有太多的经验(到目前为止我主要使用java/php/javascript) 我想要的是一个类,我在其中保存一些数据,这些数据只能由另一个类写入,但仍然可以由程序中的其他类读取 大概是这样的: public class DataObtainer{ DataItem[] Items; public DataObtainer(){ Items = new DataItem[20]; } public void Update(){ Items[0].SomePrope

我使用的是C#,我没有太多的经验(到目前为止我主要使用java/php/javascript)

我想要的是一个类,我在其中保存一些数据,这些数据只能由另一个类写入,但仍然可以由程序中的其他类读取

大概是这样的:

public class DataObtainer{
 DataItem[] Items;
 public DataObtainer(){
  Items = new DataItem[20];
 }
 public void Update(){
  Items[0].SomeProperty = 5;//Being able to change SomeProperty
 }
 //Class only contains properties
 public class DataItem{
  public int SomeProperty;
 }
}

public class AnyOtherClass{
 public void SomeMethod(){
  DataObtainer do = new DataObtainer();
  //What I want:
  DataItem di  = do.items[0];
  Console.WriteLine(di.SomeProperty);//Being able to read SomeProperty
  di.SomeProperty = 5;//Not allow this, not being able to change SomeProperty
 }
}

您应该使
DataItem
成为一个外部(非嵌套的)
abstract
类,然后创建一个内部(私有)类来继承它并提供公共mutator方法

dataactainer
中,您可以将对象强制转换为私有继承类并对其进行修改。

使用接口

public interface IData
{
   string Data1 { get;}
   int MoreData { get;}
}

class Data : IData
{
   public string Data1 { get; set;}
   public int MoreData {get; set;}
}

public class DataObtainer
{
   private Data[] items;
   public DataObtainer()
   {
      items = new Data[20];
   }
   public IEnumerable<IData> Items
   {
      get
      {
         return items;
      }
   }

   public void Update()
   {
      Items[0].MoreData = 5;//Being able to change MoreData
   }
}

public class AnyOtherClass
{
   public void SomeMethod()
   {
       DataObtainer do = new DataObtainer();
       //What I want:
       IData di  = do.Items.First();
       Console.WriteLine(di.MoreData);//Being able to read SomeProperty
       di.SomeProperty = 5;//this won't compile
   }
}
公共接口IData
{
字符串Data1{get;}
int MoreData{get;}
}
类别数据:IData
{
公共字符串Data1{get;set;}
公共数据{get;set;}
}
公共类数据获取程序
{
私有数据[]项;
公共数据获取程序()
{
项目=新数据[20];
}
公共数字项目
{
得到
{
退货项目;
}
}
公共无效更新()
{
项[0]。MoreData=5;//能够更改MoreData
}
}
公共类任何其他类
{
公共方法()
{
DataActainer do=新的DataActainer();
//我想要的是:
IData di=do.Items.First();
Console.WriteLine(di.MoreData);//能够读取SomeProperty
di.SomeProperty=5;//这不会编译
}
}
解释:

  • 创建要提供给代码的接口(IData)
  • 在该接口的实现中创建
  • 将实现存储在获取程序中
  • 仅允许其他代码访问接口。这不允许他们更改值
  • 调用代码可以根据需要对实现进行强制转换,但这样一来,它们就违反了约定,所有赌注都输掉了

  • 那种设计对我来说似乎很尴尬。您可以控制代码,因此,除非您正在设计某种框架/api,否则您要求执行的操作并不是真正必要的。如果类不能修改属性,请不要修改属性或提供setter

    如果你能多解释一下你需要完成这项工作的内容或原因,帮助我们了解为你实现目标提供的最佳方法

    使用基本继承的简单示例

    // Class used to read and write your data
    public class DataBuilder : Data {
        public void SetValue(int value) {
            base.m_SomeValue = value; // Has access to protected member
        }
    }
    
    // Class used to store your data (READONLY)
    public class Data {
        protected int m_SomeValue; // Is accessible to deriving class
        public int SomeValue {     // READONLY property to other classes
                                   // EXCEPT deriving classes
            get {
                return m_SomeValue;
            }
        }
    }
    
    public class AnyOtherClass {
        public void Foo() {
            DataBuilder reader = new DataBuilder();
            Console.WriteLine(reader.SomeValue); // *CAN* read the value
            reader.SomeValue = 100; // CANNOT *write* the value
        }
    }
    

    我不同意。你不应该只是记住不要设置一些东西。然而,语言提供了这种能力。事实上,这几乎是继承的最佳用例。这看起来很尴尬的原因是,如果你不需要设置一些东西,或者不想设置一些东西,这甚至不应该是一个问题,因为它已经是设计的一部分。然而,如果这是一个框架或API,那么它确实会带来安全/设计风险,数据可能会被修改,而这可能是不应该的。但这就是属性的全部要点,隐藏存储数据的私有成员,这样您就可以控制数据,而不会暴露这些类型的风险。继承,是的,这是做这类事情的好方法,但我也没有质疑你的答案。非常感谢你的时间和帮助。我希望属性从其他类只读的原因是因为它只是从其他地方获得的数据的表示。更改属性不会更改其他位置的数据。如果我要更改其他类中的属性,它将不再是一个正确的表示形式,因此即使我不能在任何地方更改属性,我宁愿代码不允许这样做。你的例子很好用,但是我决定使用tster发布的接口方式,因为它需要更少的额外方法和属性。如果你把具体的实现变成一个私有的内部类,其他类将无法转换为它,非常感谢!正如符文FS所说,我已经把“数据”类变成了一个私有的内部类,一切都像一个符咒一样工作!不过,我还有一个问题,在您的示例中,您使用了“IEnumerable Items”,我想知道这是否以及为什么比“IData[]Items”更好?@Wander,如果您允许他们访问IData[],那么他们可以接受它并执行类似的操作:
    acquiner.Items[1]=differentData。我的假设是,你不希望他们改变获取者中的对象。@Rune FS,是的,这是真的。虽然我基本上不担心人们投出一个基本类型和破坏合同。即使这样,如果他们真的愿意,他们仍然可以使用反射来更改值。反射部分只能在定义程序集和反射程序集之间具有足够信任的情况下工作,因此换句话说,可以“密封它”IEnumeration并不是说您不能更改序列,而是说您不能也不应该总是依赖于能够更改序列。如果您返回一个数组,您仍然可以更改元素(是的,您需要强制转换),如果您执行的是不可变序列所指定的类型(可能与IEnumerabl一起定义契约)