如何使 T 类型的字段可变?

How can I make a field of type T volatile?

我试图将一堆重复代码整合到具有以下结构的实用程序中 class:

public class Shared<T>
{
    private volatile T _value;

    public object Lock { get; private set; }

    public T Value
    {
        get { lock (Lock) return _value; }
        set { lock (Lock) _value = value; }
    }

    public Shared(T startingValue)
    {
        _value = startingValue;
        Lock = new object();
    }

    public Shared()
        : this(default(T))
    {
    }
}

但是,C#不会让我。文档指出 T 必须是引用类型或原语之一(int、bool 等)。我唯一关心的类型是引用类型和布尔值。显然,我不能使用无界类型 T。有什么办法可以使这项工作吗?甚至可以为此添加约束以使其作为 Shared<bool> 工作吗?我什至不允许将其他结构类型标记为易变的。 :(

如果无法将其标记为易失性,我是否有其他保证在多个线程尝试读取该值时它不会被优化掉?

您可以轻松地将泛型类型限制为仅引用...

public class Shared<T> where T : class

...但是也没有办法将其限制为 bool。 class 非常小,因此您可以为布尔类型创建一个特定的实现。

但是...

你在读取和写入值时的锁定完全没有用。对象引用的 read/write 在 .NET 中是原子的,因此不需要锁。它只是减慢了速度。 (布尔值被实现为一个 4 字节整数,它们也是原子的,所以你的布尔版本也不需要它)

volatile 关键字意味着每次读取值时都会确保从内存中再次读取该值。这解决了值可能缓存在寄存器或 L1/L2 缓存中的问题。在这种情况下,后续访问将是 register/cached 值,即使另一个 CPU 可能已经在主内存中更改了它。所以你的volatile会阻止值被缓存到一个寄存器中,保证每次读取都和主存一致。

(这不是特定于 volatile 问题,而是针对此类情况的可能的一般解决方法。)

您可以让您的 class 实现一个接口(例如,IShared<T>)。通过通用工厂方法构造它的实例。然后您可以提供多个实现。

对于引用类型,您可以 return 个您已有的 class 实例,限制为 T : class。对于原始类型,您可以 return 实现 IShared<bool>IShared<int> 等的专用非泛型 classes 的实例