C#从get中返回一个只读变量;组;

时间:2009-06-02 13:33:38

标签: c# properties readonly

我发誓我已经看过这样的一个例子,但谷歌搜索了一下,找不到它。

我有一个类,它有一个对象的引用,需要有一个GET;它的方法。我的问题是我不希望任何人能够摆弄它,即我希望他们得到它的只读版本(注意我需要能够在我的班级内改变它)。

由于

7 个答案:

答案 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));

这可以帮助其他人只为特定情况公开那些属性并且可以管理它们。