如何创建T类型的字段?

时间:2015-03-04 23:13:14

标签: c# generics

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

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等)。我关心的唯一类型是引用类型和bools。显然,我不能使用无界类型T。有没有办法让这项工作成功?甚至可以为此添加约束以使其作为Shared<bool>工作吗?我甚至不允许将其他结构类型标记为volatile。 :(

如果没有可能的方法将其标记为volatile,我是否还有其他保证,当多个线程尝试读取此值时,它不会被优化掉?

2 个答案:

答案 0 :(得分:4)

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

public class Shared<T> where T : class

...但是也无法将此限制为 bool 。该类非常小,因此您可以为布尔类型创建特定的实现。

<强> BUT ...

在读取和写入值期间锁定完全没用。对象引用的读/写在.NET中是原子的,因此不需要锁。它只会减慢速度。 (布尔值实现为4字节整数,它们也是原子的,因此布尔版本也不需要它)

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

答案 1 :(得分:1)

(这不是针对volatile问题的具体问题,而是针对此类案例的可能的一般解决方法。)

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

对于引用类型,您可以返回已有类的实例,约束为T : class。对于基本类型,您可以返回实现IShared<bool>IShared<int>等的专用非泛型类的实例。