Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/actionscript-3/6.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# - Fatal编程技术网

C#-如何防止引用类成员?

C#-如何防止引用类成员?,c#,C#,我有一个类(myClass),它包含一个私有类成员(myData类型的currentData)。我有一个属性(CurrentData),允许“获取”该成员。我希望允许用户调用currentData上的函数,但防止他们获取对它的外部引用。例如 myClass a = new myClass(); // This is OK a.CurrentData.somefunc(); // This is what I dont want myData m = new myData(); m = a.C

我有一个类(myClass),它包含一个私有类成员(myData类型的currentData)。我有一个属性(CurrentData),允许“获取”该成员。我希望允许用户调用currentData上的函数,但防止他们获取对它的外部引用。例如

myClass a = new myClass();

// This is OK
a.CurrentData.somefunc();

// This is what I dont want
myData m = new myData();
m = a.CurrentData;
// ... some time passes here...
m.someFunc();
据我所知,它们指的是同一个物体。我不希望在我的类之外保留对内部成员的引用,因为该内部成员可能会意外更改


这可能吗?我离开c#太久了,我记不起这一切是怎么回事了

没有办法

a.CurrentData.somefunc();
合法但

m = a.CurrentData;
非法的<代码>a.CurrentData.somefunc()本质上返回对
a.CurrentData
的内联引用,然后对该引用调用
somefunc()

如果要阻止对内部对象的引用,则必须向包含类添加方法,然后将这些方法传递到包含的对象:

public void DoSomeFuncWithCurrentData()
{
   this.currentData.someFunc();
}

myClass a = new myClass();

a.DoSomeFuncWithCurrentData();

您不能阻止用户获取对对象的外部引用,但可以通过以下两种方式之一使此类引用不相关:

  • 使内部对象不可变-这样外部引用就不可能更改对象内部的内容。这就是.NET库对字符串所做的
  • 返回一个防御性副本-这样可以允许外部修改,但它们会发生在对象的副本上
另一种可能是使类成为结构,在这种情况下,根本不可能创建引用。这应该非常小心,因为使用值类型还有其他含义。

没有直接的方法“禁止”引用

但是,有一些可能的解决办法:

  • 创建代理方法:根本不允许公共访问
    CurrentData
    属性。为可以对CurrentData调用的每个方法创建代理方法:

    myClass a = new myClass();
    a.SomeFuncOnCurrentData();
    
    这样就不会将类的内部工作公开给外部。缺点是您必须编写大量样板代码(或者使用第三方工具为您编写样板代码)

  • 返回副本:用
    GetCurrentData
    方法替换
    CurrentData
    属性,并在每次调用时返回内部对象的新副本。这样,用户可以根据自己的需要对“旧”数据进行操作,并且用户的对象与您的内部对象断开连接

  • 替换内部对象并保持旧对象不变:使
    MyData
    成为不可变的类。当
    CurrentData
    更改时,不要修改MyData,而是创建一个新的MyData对象。这与上一点(返回副本)的效果相同,但您可以继续使用不需要在每次调用时创建副本的属性

  • 使旧的内部对象无效:当
    CurrentData
    更改时,执行以下步骤:

    • 在内部使用
      MyData
      的新实例
    • 在旧实例上设置标志,这将导致
      someFunc
      抛出
      ObjectExpiredException
如果可以:

a.CurrentData.somefunc();
但这并不好:

var currentData = a.CurrentData;
currentData.someFunc();
那么,从句法上(即静态上)就不能禁止在将来的任意时间使用引用。您最好将此需求构建到包含类中,
myClass
。如果将方法
someFunc()
作为
myClass
上的方法公开,则仅当它们引用了
myClass
时,才隐式允许调用(内部)函数


此外,如果这是一个好的解决方案,您应该删除
CurrentData
属性,因为它正在发布一个私有的表面积。将
myClass
需要从
CurrentData
公开的任何方法作为
myClass
上的方法进行传播,这很遗憾,但不可能。另一个选项是返回包装器对象,而不是对象本身。我想在内心深处我知道这个问题的答案,但希望不是这样!