【问题标题】:Is it possible to have fields that are assignable only once?是否可以有只能分配一次的字段?
【发布时间】:2009-10-20 07:10:36
【问题描述】:

我需要一个可以从我想要的任何地方分配的字段,但应该可以只分配一次(因此后续的分配应该被忽略)。我该怎么做?

【问题讨论】:

  • 如果你可以在任何你想要的地方分配它,它几乎不是“只读”的,是吗?你到底想要什么?
  • 这很可能是我很长时间以来见过的最奇怪的要求之一。为什么需要一个非只读的只读字段?
  • 我需要一个只能在第一次分配的只读字段。我想要的是目前 C# 中的只读字段,但我希望它的第一个赋值可以在构造函数以外的地方进行。我想用它来跟踪数据的变化。
  • @afsharm:我冒昧地编辑了您的问题,以描述更多我认为您实际要求的内容。我希望我做对了;否则,只需根据自己的喜好对其进行编辑。
  • 这可能就是你要找的东西:stackoverflow.com/questions/839788/…

标签: c# readonly


【解决方案1】:

那将不是一个只读字段。初始化真正的只读字段的唯一选择是字段初始化器和构造器。

但是,您可以使用属性实现一种只读功能。将您的字段设为属性。实现一个“冻结实例”方法,该方法翻转一个标志,表明不允许对只读部分进行更多更新。让你的二传手检查这个标志。

请记住,您正在放弃编译时检查以进行运行时检查。如果您尝试从除声明/构造函数之外的任何地方为只读字段分配值,编译器会告诉您。使用下面的代码,您将得到一个异常(或者您可以忽略更新 - 这两者都不是最佳 IMO)。

编辑:为避免重复检查,您可以将只读功能封装在一个类中。

修改后的实现可能如下所示:

class ReadOnlyField<T> {
    public T Value {
        get { return _Value; }
        set { 
            if (Frozen) throw new InvalidOperationException();
            _Value = value;
        }
    }
    private T _Value;

    private bool Frozen;

    public void Freeze() {
        Frozen = true;
    }
}


class Foo {
    public readonly ReadOnlyField<int> FakeReadOnly = new ReadOnlyField<int>();

    // forward to allow freeze of multiple fields
    public void Freeze() {
        FakeReadOnly.Freeze();
    }
}

然后你的代码可以做类似的事情

        var f = new Foo();

        f.FakeReadOnly.Value = 42;

        f.Freeze();

        f.FakeReadOnly.Value = 1337;

最后一条语句会抛出异常。

【讨论】:

  • 我目前正在使用这样的“冻结实例”解决方案,但我的班级有这么多字段,为每个字段添加 5 行是没有意义的。但是“字段初始化器”呢?我不知道它是什么。是否可以分配给那里的只读字段?这和“属性”一样吗?
  • 没有字段初始化器不会帮助你。您无法使用常规的只读字段完成您所要求的操作。
  • @afsharm - 如果不值得为每个字段添加 5 行,那么您显然不需要此功能(不确定您为什么会这样做)。
  • 请考虑问题本身和所有答案中的 cmets。
【解决方案2】:

尝试以下方法:

class MyClass{
private int num1;

public int Num1
{
   get { return num1; }

}


public MyClass()
{
num1=10;
}

}

【讨论】:

    【解决方案3】:

    或者您的意思是每个人都可以读取但只有类本身可以写入的字段?在这种情况下,请使用带有公共 getter 和私有 setter 的私有字段。

    private TYPE field;
    
    public TYPE Field
    {
       get { return field; }
       private set { field = value; }
    }
    

    或使用自动属性:

    public TYPE Field { get; private set; }
    

    【讨论】:

    • 不!我不是这个意思!事实上,我有一个由 NHibernate 从数据库填充的对象,然后传递给 UI。用户可以编辑或不编辑某些字段,但我应该不允许更改某些特定字段。我认为我可以实现的方法之一是将每个字段的影子字段定义为只读,然后将此影子字段与原始字段进行比较,并了解是否发生了更改。请考虑在构造函数中未填充这些字段。
    • 这样做不是更好吗,这样用户只能编辑其中一些,使只读字段显示在标签而不是文本框中,或者类似的?如果您使用的是属性网格,您可以在其上方粘贴 [ReadOnly] 属性。
    • 这是 SOA 应用程序。我们在 web、winform 和控制台中有 UI,我不能在 SERVICE 之外的任何地方这样做。
    猜你喜欢
    • 2015-02-19
    • 2016-06-18
    • 2015-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多