问题描述
来自 C++ 背景,我习惯于将 const
关键字粘贴到函数定义中,以使对象以只读值传递.但是,我发现这在 C# 中是不可能的(如果我错了,请纠正我).经过一番谷歌搜索,我得出的结论是,制作只读对象的唯一方法是编写一个只有获取"属性的接口,然后将其传入.优雅,我必须说.
Coming from a C++ background, I'm used to sticking the const
keyword into function definitions to make objects being passed in read-only values. However, I've found out that this is not possible in C# (please correct me if I'm wrong). After some Googling, I arrived at the conclusion that the only way to make a read-only object is to write an interface that only has 'get' properties and pass that in instead. Elegant, I must say.
public interface IFoo
{
IMyValInterface MyVal{ get; }
}
public class Foo : IFoo
{
private ConcreteMyVal _myVal;
public IMyValInterface MyVal
{
get { return _myVal; }
}
}
我会把它传递给:
public void SomeFunction(IFoo fooVar)
{
// Cannot modify fooVar, Excellent!!
}
这很好.但是,在我的其余代码中,我想正常修改我的对象.向界面添加设置"属性会打破我的只读限制.我可以向 Foo
(而不是 IFoo
)添加一个set"属性,但签名需要一个接口而不是具体对象.我必须做一些选角.
This is fine. However, in the rest of my code, I would like to modify my object normally. Adding a 'set' property to the interface would break my read-only restriction. I can add a 'set' property to Foo
(and not IFoo
), but the signature expects an interface rather than a concrete object. I would have to do some casting.
// Add this to class Foo. Might assign null if cast fails??
set { _myVal = value as ConcreteMyVal; }
// Somewhere else in the code...
IFoo myFoo = new Foo;
(myFoo as Foo).MyFoo = new ConcreteMyVal();
有没有更优雅的方法来复制 const
或制作只读函数参数而不添加其他属性或函数?
Is there a more elegant way of replicating const
or making read-only function parameters without adding another property or a function?
推荐答案
我认为您可能正在寻找一种解决方案,其中涉及两个接口,其中一个继承自另一个:
I think you may be looking for a solution involving two interfaces in which one inherits from the other:
public interface IReadableFoo
{
IMyValInterface MyVal { get; }
}
public interface IWritableFoo : IReadableFoo
{
IMyValInterface MyVal { set; }
}
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public IMyValInterface MyVal
{
get { return _myVal; }
set { _myVal = value as ConcreteMyVal; }
}
}
然后您可以声明其参数类型告诉"它是否计划更改变量的方法:
Then you can declare methods whose parameter type "tells" whether it plans on changing the variable or not:
public void SomeFunction(IReadableFoo fooVar)
{
// Cannot modify fooVar, excellent!
}
public void SomeOtherFunction(IWritableFoo fooVar)
{
// Can modify fooVar, take care!
}
这模仿了类似于 C++ 中的 constness 的编译时检查.正如 Eric Lippert 正确指出的那样,这与不变性不相同.但作为一名 C++ 程序员,我想你知道这一点.
This mimics compile-time checks similar to constness in C++. As Eric Lippert correctly pointed out, this is not the same as immutability. But as a C++ programmer I think you know that.
顺便说一句,如果将类中的属性类型声明为ConcreteMyVal
并单独实现接口属性,则可以实现稍微更好的编译时检查:
By the way, you can achieve slightly better compile-time checking if you declare the type of the property in the class as ConcreteMyVal
and implement the interface properties separately:
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public ConcreteMyVal MyVal
{
get { return _myVal; }
set { _myVal = value; }
}
public IMyValInterface IReadableFoo.MyVal { get { return MyVal; } }
public IMyValInterface IWritableFoo.MyVal
{
// (or use "(ConcreteMyVal)value" if you want it to throw
set { MyVal = value as ConcreteMyVal; }
}
}
这样,setter 只能在通过接口访问时抛出,而在通过类访问时不能.
This way, the setter can only throw when accessed through the interface, but not when accessed through the class.
这篇关于C# 的只读(类似“const")函数参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!