【问题标题】:C# return a variable as read only from get; set;C# 从 get 中返回一个只读变量;放;
【发布时间】:2009-06-02 13:33:38
【问题描述】:

我发誓我见过这样的一个例子,但已经用谷歌搜索了一段时间,找不到它。

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

谢谢

【问题讨论】:

  • 我很惊讶有多少人误解了这个问题。 Jon Skeet 和 Anton Gogolev 做对了。
  • 我认为我没有误解 - 但仍然被否决 - 哦,好吧
  • @ChrisCudmore 我不认为 Anton Gogolev 是这里的主题。而对于乔恩来说——好吧,他只是把事情做对了:)

标签: c# properties readonly


【解决方案1】:

不,没有办法做到这一点。例如,如果您返回 List<string>(并且它不是不可变的),那么调用者 能够添加条目。

解决这个问题的正常方法是返回一个不可变的包装器,例如ReadOnlyCollection<T>.

对于其他可变类型,您可能需要在返回值之前对其进行克隆。

请注意,仅返回不可变的接口视图(例如,返回 IEnumerable<T> 而不是 List<T>)不会阻止调用者转换回可变类型并进行变异。

编辑:请注意,除此之外,这种担忧是不可变类型更容易推理代码的原因之一 :)

【讨论】:

  • 首先你说它做不到,然后你指向克隆解决方案。此外,也许克隆对于 c# 来说是一个新想法,但它在 c++ 中已经存在了很长时间,例如。它也不是严格的克隆——它是创建内部数据的副本并返回这个副本,而不是原始数据——副本不必与原始数据的类型相同。
【解决方案2】:

返回对精简接口的引用:

 interface IFoo
   string Bar { get; }

 class ClassWithGet
   public IFoo GetFoo(...);

【讨论】:

  • 理想情况下包括privateinternal IFoo 的实现,这样它就不能被回滚;)
  • 嗯,不,如果接口是内部的或私有的,您将无法返回具有不可访问类型的公共成员。这不会编译:“不一致的可访问性:字段类型...比字段...更难访问”
【解决方案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 类的实例,这样他们就可以只使用你允许他们看到的东西。

如果您的基类不是一成不变的,这可能会变得有点复杂,并且可能无法很好地扩展,但对于大多数简单的情况,它可能只是解决问题。我认为这被称为外观模式(但不要引用我的话=))

【讨论】:

  • 这是我正在寻找的解决方案。我还应该补充一点,即使您要包装的对象很复杂,也不意味着您必须实际包装每个方法/函数。就我而言,我只是想包装一个非常复杂的对象,并且只展示某些方法。例如,您的复杂对象可以有 20 个方法,但您的包装对象只能访问 5 个。
【解决方案4】:

这是不可能的。获取和设置引用类型的访问器获取和设置对对象的引用。您可以通过使用私有(或内部)setter 来阻止对引用的更改,但如果对象被 getter 公开,则无法阻止对对象本身的更改。

【讨论】:

  • 是的,这是可能的。您可以返回数据的副本。
【解决方案5】:

您的问题看起来像您正在寻找:

public PropertyName { get; private set; }

但是,鉴于到目前为止的答案,我不确定我是否正确解释了您的问题。此外,我有什么资格去质问 Jon Skeet? :)

【讨论】:

  • 返回一个只读的引用,因为它不能被赋值,但是你仍然可以编辑这个对象,因为它的属性不是只读的
  • 这对我有帮助!保持公开但不可写的东西是多么聪明的方法
【解决方案6】:

我同意 ReadOnlyCollection

查看我的简单代码:

 private List<Device> _devices;
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices 
{
 get
 { 
return (_devices.AsReadOnly());
 } 

}

ReadOnlyCollection 没有 Add 方法,因此用户无法向其添加属性。但不保证用户是否可以通过调用对象的方法来修改对象......

【讨论】:

    【解决方案7】:

    我以某种方式遇到过这个问题。 我有一个 CategoryViewModel 类,它有一个我想要私有只读的属性 Category:

    public CategoryViewModel
    {
        private Category { get; }
    
    }
    

    事实上,我希望它以只读方式导出到其他类。但是我不能做这样的事情。 就我而言(也许它会帮助其他一些人),我想将它添加到存储库中。我发现的唯一方法是将存储库作为参数 1 的函数,将操作作为参数 2:

    public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action)
    {
        action(repo, Category);
    }
    

    像那样,从其他地方,我可以做这样的事情:

     categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c));
    

    这可以帮助其他人仅在某些情况下公开那里的属性并可以管理它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-25
      • 1970-01-01
      • 1970-01-01
      • 2017-06-21
      • 2012-09-08
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      相关资源
      最近更新 更多