C# 泛型类中静态字段的合适解决方法?

C# 泛型类中静态字段的合适解决方法?,c#,generics,inheritance,C#,Generics,Inheritance,鉴于泛型类型为每个类型组合创建单独的静态字段实例,如果我希望在所有类型中都有一个静态字段,那么这是一种有效的模式吗 public class BaseClass { public static int P = 0; } public class ChildClass<T> : BaseClass { public static int Q = 0; public void Inc() { // ChildClass<int&g

鉴于泛型类型为每个类型组合创建单独的静态字段实例,如果我希望在所有类型中都有一个静态字段,那么这是一种有效的模式吗

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); 
    }
}
公共类基类
{
公共静态int P=0;
}
公共类子类:基类
{
公共静态int Q=0;
公共空间公司
{
//ChildClass将具有与ChildClass不同的“Q”
联锁增量(参考Q);
//所有类型的子类都将增加相同的P
联锁增量(参考P);
}
}
这种方法有什么不安全的地方吗?我的玩具示例很有效,但我只是想确保没有可怕的副作用、线程后果等:)

您可以使用更多线程安全代码

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
}
请注意,对于每个
T
将有一个不同的
ChildClass.Q
,但只能有一个
BaseClass.p
。这意味着您必须使用单独的锁对象来处理
Q
P
(从技术上讲,用于锁定
P
的任何对象也可以用于锁定所有
Q
,但这可能不是您想要做的事情)。

您可以使用更多线程安全的代码

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
}

请注意,对于每个
T
将有一个不同的
ChildClass.Q
,但只能有一个
BaseClass.p
。这意味着您必须使用单独的锁对象来处理
Q
P
(从技术上讲,用于锁定
P
的任何对象也可以用于锁定所有
Q
,但这可能不是您想要做的事情)。

您的模式是有效的,没有问题。没有静态继承这样的东西,但是您可以像通常一样访问任何类型的静态成员(前提是它们对派生类可见,例如not

private
):

BaseClass.P=10;
儿童班,Q=20;
C#规范规定,对32位整数(即,
int
)的单次读取或写入是原子的,这意味着它们可以在一条指令内完成,而另一个线程永远看不到半写变量

12.5变量引用的原子性

以下数据类型的读写应为原子型:bool、char、byte、sbyte、short、ushort、uint、int、float和引用类型。此外,前面列表中具有基础类型的枚举类型的读写也应是原子的。其他类型(包括long、ulong、double和decimal)以及用户定义类型的读写不需要是原子的

当然,阅读和写作并不能保证是原子的。例如,增加一个变量的值需要先读后写,这就是变量的作用所在


顺便说一句,您可能知道您只会得到一个
p
静态变量,但是由于您的类型有不同的泛型实例
ChildClass
,您的模式是有效的,没有问题。没有静态继承这样的东西,但是您可以像通常一样访问任何类型的静态成员(前提是它们对派生类可见,例如not
private
):

BaseClass.P=10;
儿童班,Q=20;
C#规范规定,对32位整数(即,
int
)的单次读取或写入是原子的,这意味着它们可以在一条指令内完成,而另一个线程永远看不到半写变量

12.5变量引用的原子性

以下数据类型的读写应为原子型:bool、char、byte、sbyte、short、ushort、uint、int、float和引用类型。此外,前面列表中具有基础类型的枚举类型的读写也应是原子的。其他类型(包括long、ulong、double和decimal)以及用户定义类型的读写不需要是原子的

当然,阅读和写作并不能保证是原子的。例如,增加一个变量的值需要先读后写,这就是变量的作用所在


顺便说一句,您可能知道您只会得到一个
p
静态变量,但是由于您的类型
ChildClass

有不同的泛型实例,所以会得到同样多的
Q
静态变量。编辑:另外,我假设您希望控制get/set访问(您希望它是公开设置的,还是只在
Inc
方法中私下递增?)哈哈,这是一个很好的观点。我对我的例子不必那么粗心。假设某个互锁的东西或其他东西。我要处理的实际问题是,我想要一个线程安全队列,但向这个内部队列添加东西的类是泛型的。所以“价值”不会公开设定。那么是的,我认为没有真正的问题。请记住,
对于所使用的任何特定子类或接口都是唯一的。所以
ChildClass
ChildClass
有不同的
Q
,与
ChildClass
ChildClass
相同。我想特别是关于你的问题,不,这没有可怕的副作用。只要您了解
Q
相对于
T
的唯一性,那么在这样的泛型类中利用静态成员是完全有效的。可能最重要的是,如果要在
ChildClass
上创建锁定对象(如
private static object LockingObject=new object()
),您需要认识到锁不会在不同的具体
ChildClass
类型之间共享。如果需要共享锁,则需要在
BaseClass上定义对象
BaseClass.P = 10;
ChildClass<string>.Q = 20;