我发誓我已经看过这样的一个例子,但谷歌搜索了一下,找不到它。
我有一个类,它有一个对象的引用,需要有一个GET;它的方法。我的问题是我不希望任何人能够摆弄它,即我希望他们得到它的只读版本(注意我需要能够在我的班级内改变它)。
由于
答案 0 :(得分:52)
不,没有办法做到这一点。例如,如果您返回List<string>
(并且它不是不可变的),则呼叫者将能够添加条目。
这种方法的正常方法是返回一个不可变的包装器,例如: ReadOnlyCollection<T>
对于其他可变类型,您可能需要在返回之前克隆该值。
请注意,只返回一个不可变的接口视图(例如,返回IEnumerable<T>
而不是List<T>
)将不会阻止调用者返回到mutable类型并进行变异。
编辑:请注意,除了其他任何内容之外,这种关注是不可变类型更容易推理代码的原因之一:)
答案 1 :(得分:6)
返回对精简界面的引用:
interface IFoo
string Bar { get; }
class ClassWithGet
public IFoo GetFoo(...);
答案 2 :(得分:3)
这是不可能的。获取和设置引用类型的访问器获取并设置对象的引用。您可以使用私有(或内部)setter来阻止对引用的更改,但如果它被getter公开,则无法阻止对对象本身的更改。
答案 3 :(得分:3)
如果对象不是太复杂/粗糙,那么在它周围写一个包装。
例如:
class A {
public string strField = 'string';
public int intField = 10;
}
class AWrapper {
private A _aObj;
public AWrapper(A aobj) {
_aObj = A;
}
public string strField {
get {
return _aObj.strField;
}
}
public int intField {
get {
return _aObj.intField;
}
}
}
所以现在你所做的就是给你的客户端代码一个AWrapper类的实例,这样他们就可以只使用你允许他们看到的内容了。
这可能会有点复杂,如果您的基类没有一成不变,可能无法很好地扩展,但对于大多数简单情况,它可能只是诀窍。我认为这被称为门面模式(但不要引用我=))
答案 4 :(得分:2)
您的问题就像是在寻找:
public PropertyName { get; private set; }
但是,到目前为止,鉴于答案,我不确定我是否正确地解释了你的问题。此外,我是谁来质疑Jon Skeet? :)
答案 5 :(得分:0)
我同意ReadOnlyCollection
请参阅我的简单代码:
private List<Device> _devices;
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices
{
get
{
return (_devices.AsReadOnly());
}
}
ReadOnlyCollection没有添加方法,因此用户无法向其添加属性。但是,如果用户可以通过调用方法修改对象,则无法保证.......
答案 6 :(得分:0)
我以某种方式面对这个问题。 我有一个CategoryViewModel类,它有一个我想要私有只读的属性Category:
public CategoryViewModel
{
private Category { get; }
}
实际上,我希望它以只读方式导出到其他类。但是我不能做这样的事情。 在我的情况下(也许它会帮助其他人),我想将它添加到存储库。我找到的唯一方法是将一个函数与存储库作为参数1,将一个Action作为参数2:
public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action)
{
action(repo, Category);
}
就像那样,从其他地方来说,我可以这样做:
categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c));
这可以帮助其他人只为特定情况公开那些属性并且可以管理它们。