适用于泛型类中的静态字段
本文关键字:静态 字段 泛型类 适用于 | 更新日期: 2023-09-27 18:05:07
给定泛型类型为每个类型组合创建静态字段的单独实例,如果我想要跨所有类型拥有静态字段,那么使用这种模式有效吗?
public class BaseClass
{
public static int P = 0;
}
public class ChildClass<T> : BaseClass
{
public static int Q = 0;
public void Inc()
{
// ChildClass<int> will have a different "Q" than ChildClass<double>
Interlocked.Increment(ref Q);
// all types of ChildClass will increment the same P
Interlocked.Increment(ref P);
}
}
这种方法有什么不安全的地方吗?我的玩具示例工作,但我只是想确保没有可怕的副作用,线程后果等:)
您可以使用Interlocked。增加更多线程安全的代码。
public void Inc()
{
Interlocked.Increment(ref Q); // ChildClass<int> will have a different "Q" than ChildClass<double>
Interlocked.Increment(ref P); // all types of ChildClass will increment the same P
}
或原lock
public class BaseClass
{
protected static int P = 0;
protected static object pLock = new object();
}
public class ChildClass<T> : BaseClass
{
private static int Q = 0;
private static object qLock = new object();
public void Inc()
{
lock(qLock)
{
qLock++;
}
lock(pLock)
{
qLock++;
}
}
}
注意,对于每个T
,将有一个不同的ChildClass<T>.Q
,但只能有一个BaseClass.P
。这意味着您必须使用单独的锁对象来处理Q
和P
(技术上用于锁定P
的任何东西也可以用于锁定所有Q
,但这可能不是您想要做的)。
您的模式是有效的,没有问题。没有静态继承这样的东西,但是您可以像通常那样访问任何类型的静态成员(只要它们对派生类可见,例如不是private
):
BaseClass.P = 10;
ChildClass<string>.Q = 20;
c#规范指出,对32位整数(即int
)的单次读写是原子性的,这意味着它们可以在单个指令中完成,并且不会在另一个线程中看到写入一半的变量。
当然,读和写不能保证是原子的。例如,增加变量的值需要先读后写,这就是12.5变量引用原子性
下列数据类型的读写必须是原子类型:bool、char、byte、sbyte、short、ushort、uint、int、float和引用类型。此外,具有前面列表中基础类型的枚举类型的读写也必须是原子的。其他类型(包括long、ulong、double和decimal)以及用户定义类型的读写不需要是原子类型。
Interlocked
方法发挥作用的地方。
顺便说一下,您可能意识到您将只获得一个P
静态变量,但是Q
静态变量的数量与您的类型ChildClass<T>
的不同通用实例一样多。