C#标记成员为"不使用"

niv*_*lam 24 c# encapsulation

public class Demo
{
    private List<string> _items;
    private List<string> Items
    {
        get
        {
            if (_items == null)
                _items = ExpensiveOperation();

            return _items;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Demo该类中的其他方法将可以访问该_items字段.由于我使用属性来延迟加载项目,我不希望其他开发人员错误地尝试使用该_items字段.

我知道我可以使用的是ObsoleteAttribute,但是这个领域在技术上并不过时.

有没有更好的方法将会员标记为"不使用"?

Rub*_*ink 48

虽然它不是你想要做的一般技术(并且没有一个,并且,正如其他答案所涵盖,你需要信任其他开发者),在这个例子中,你可以创建一个Lazy<List<T>>(假设.NET 4或更高版本) - 虽然很容易向后移动)

class Demo {
    readonly Lazy<List<string>> _items;
    public Demo() {
        var _items = new Lazy<List<string>>( ExpensiveOperation);
    }
    List<string> Items { get { return _items.Value; }}
 }
Run Code Online (Sandbox Code Playgroud)

readonly/非易变的方法通常是去支持字段无论哪种方式的方式.

编辑:基于@Timwi的答案(如果你喜欢这个想法,请去+1)可以去城里,并且在JavaScript样式中使用基于能力的限制甚至不暴露Lazy字段,只是关闭它的操作(也纳入@Mr Disappointment的ReadOnlyCollection建议):

class Demo {
    readonly Func<ReadOnlyCollection<string>> _getItems;
    public Demo() {
        var items = new Lazy<List<string>>( ExpensiveOperation);
        _getItems = () => items.Value.AsReadOnly();
    }
    ReadOnlyCollection<string> Items { get { return _getItems(); }}
 }
Run Code Online (Sandbox Code Playgroud)

从而使我们愚蠢的编码技巧发挥作用.

  • 是的,虽然其他开发人员仍然可以直接访问`_items`,但这并不重要.该字段不能被覆盖(它是`readonly`),并且保证初始化逻辑由`Lazy <T>`类运行.如果`ExpensiveOperation`只应执行一次,即使多个线程同时访问该字段,也可以考虑将"LazyThreadSafetyMode.ExecutionAndPublication"提供给构造函数. (6认同)
  • 我认为这是正确的方式,因为它驳斥了可能被滥用的字段的使用 (3认同)
  • 难道这只是让它看起来很复杂,让开发人员第二眼看到了吗?它只限制了`_items`及其基础列表的重新分配,这意味着仍然可以操纵元素.这可以通过`readonly List <string> _items`来实现并按需填充.也许应该使用`readonly ReadOnlyCollection <string>`. (2认同)
  • "[...]而且没有一个,正如其他答案所涵盖的那样,你需要相信其他开发者" - 这不是真的,请参阅我的回答. (2认同)

Ian*_*son 43

_items字段重命名为_heyFutureDeveloperDoNotReferenceThisFieldMmmkay


Jon*_*art 12

如果您设置了这样的属性,那么Itemsgetter 如何访问它而不会生成相同的警告/错误,无论您要查找的是什么?

你是什​​么意思"另一个开发者?" 如果你的意思是另一个开发人员处理这个相同的代码(和你一起),那么一个简单的评论如下:

///<summary>Do not access directly, using lazy initialization in getter.</summary>
Run Code Online (Sandbox Code Playgroud)

应该足够了,因为Visual Studio会在鼠标悬停在字段上时显示.

如果你的意思是有人使用这个类,那么这就是隐藏信息的重点,你很高兴.


Tim*_*mwi 6

是的,有一种相对简单的方法.有些人可能认为它是黑客,但我认为这是合法的.它使用局部变量作用域规则来实现您想要的方法级隐私:

public class Demo
{
    private readonly Func<List<string>> _getItems;

    public Demo()
    {
        List<string> items = null;
        _getItems = () =>
        {
            if (items == null)
                items = ExpensiveOperation();
            return items;
        };
    }

    public List<string> Items { get { return _getItems(); } }
}
Run Code Online (Sandbox Code Playgroud)

现在变量items被正确地限定为使用它的方法.它仍然可以访问_getItems,但这样做是无关紧要的,因为它完全相同Items.无法修改,items因为它是本地的或_getItems因为它是只读的.