Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.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中实现只读(不可变)对象接口#_C#_Interface_Abstract Class_Immutability_Readonly - Fatal编程技术网

C# 在C中实现只读(不可变)对象接口#

C# 在C中实现只读(不可变)对象接口#,c#,interface,abstract-class,immutability,readonly,C#,Interface,Abstract Class,Immutability,Readonly,我的目标是确保在大多数情况下,对象通过“只读接口”使用,该接口是完整接口的子集 作为一个例子,如果我使用C++,我只返回一个 const 在C#中,如果我可以通过接口实现这一点,我只需要实现一个只读接口并在任何地方使用它。但是,我需要运算符重载,这是接口不允许的。这就是为什么我必须使用抽象基类 但是,如果我定义了一个抽象基类,我就不允许更改派生类型中的可访问性 那么,如何实现我在C#中的目标呢?您可以通过对象中的状态实现只读行为,如果调用了修改方法,则抛出异常?如果您将写操作放在接口中,然

我的目标是确保在大多数情况下,对象通过“只读接口”使用,该接口是完整接口的子集

  • 作为一个例子,如果我使用C++,我只返回一个<代码> const
  • 在C#中,如果我可以通过接口实现这一点,我只需要实现一个只读接口并在任何地方使用它。但是,我需要运算符重载,这是接口不允许的。这就是为什么我必须使用抽象基类
  • 但是,如果我定义了一个抽象基类,我就不允许更改派生类型中的可访问性

那么,如何实现我在C#中的目标呢?

您可以通过对象中的状态实现只读行为,如果调用了修改方法,则抛出异常?

如果您将写操作放在接口中,然后显式地在抽象基类上实现,又如何?这不是一个100%完美的解决方案(您仍然可以将对象强制转换到修改接口),但在大多数情况下,它可以防止任何人意外调用修改方法。

您真的需要运算符重载吗?我们在这里讨论的是语法糖。此外,并非所有.NET语言都以相同的方式使用运算符重载。因此,如果使用运算符重载,则实际上是使代码语言特定


我将实现只读接口并放弃运算符重载要求。

如果有人对我所做的感兴趣,我最终选择了一个抽象类而不是接口,并且我确实在派生类中隐藏了该方法以获得正确的访问器:

例如,在基本抽象类(只读接口)中:

在派生类中:

public new double Accuracy
{
    get { return accuracy; }
    set { accuracy = value; }
}

当然,丑陋与“新”关键字,但在这种情况下,它会为我做。

@Chris-在另一个应用程序中,我完全同意:)我几乎做到了。在这个例子中(计算性的)——删除它是非常不幸的,实际上比删除只读需求更不幸……只读,或常量,因为参数约束也是我希望在C#中看到的。创建只读接口并不是最好的解决方案。但有时你不得不使用你正在使用的语言。@Vilx-我喜欢你的建议,不过,我决定不去做,因为J.Richter建议尽量避免显式接口实现……特别是,因为我会做很多这样的转换,即使我是派生类型,为什么不创建一个包含读写方法的接口呢?隐式实现读取方法,显式实现写入方法。然后您只需将其强制转换一次即可获得读写对象。我在类中做了类似的操作,在这些类中,我提供了
只读
属性和
保存
方法。如果类的实例是
ReadOnly
true
,则调用
Save
将抛出
invalidooperationexception
。也就是说,这个场景没有你描述的那么严格。此类类的实例可以由其他方法和属性进行变异。但是,无法保存该实例(例如,保存到磁盘)。
public new double Accuracy
{
    get { return accuracy; }
    set { accuracy = value; }
}