最近我对在数百个线程使用的类中使用静态方法存在争议。 在我看来,“第一”解决方案没有特别的好处,除了它更容易用于课堂的客户,但我被告知这是非常糟糕的主意,我必须使用“第二”解决方案。谁能给我清楚解释为什么我这么错? 非常感谢!
PS 我们假设字典是线程安全的。
class A
{
static Dictionary<int, string> m_dic = new Dictionary<int, string>();
public static string GetData1(int nKey)
{
return m_dic[nKey];
}
public string GetData2(int nKey)
{
return m_dic[nKey];
}
}
//these func are called from threads...
void ThreadFunc1()
{
print A.GetData1(1);
}
void ThreadFunc2()
{
A a = new A();
print a.GetData2(1);
}
此致 列昂尼德
答案 0 :(得分:5)
使用实例成员暗示(至少对我来说)与实例本身有关 - 它的状态,或者可能它在覆盖方面的行为方法(即“状态”是实例的执行时类型。)
在这种情况下,这些都不是 - 所以我会将实例视为坏样式,导致误导代码。
答案 1 :(得分:3)
如果线程需要访问线程安全的 共享 资源,则静态类完全可行。所以你没错。
答案 2 :(得分:2)
我肯定会使用静态方法,因为Jon说的所有原因加上我想再添加一个。请考虑以下在多线程环境中运行的代码。
void ThreadFunc2()
{
var a = new A();
if (a.GetData2(1) == "foo")
{
DoSomething(a.GetData2(1));
}
}
一个毫无戒心的程序员创建了一个A
的新实例,天真地对GetData2
进行两次调用,这些调用是相互依赖的,认为没有任何问题可能会出错,因为A
实例在其他任何地方都没有使用过。但问题是没有保证GetData2
第二次会返回相同的东西,因为另一个线程可能已经改变了该方法使用的静态字典。当您使用实例方法提取静态时,这完全不明显。
我并不是说使用实例成员来读取静态状态一定是错误的。我所说的是它有 potential 引起问题,特别是当暗示可以安全地从多个线程同时使用单独的对象实例时。
答案 3 :(得分:1)
C#中的静态数据可以与C ++,Delphi和其他语言中的global variables进行比较。它们往往很糟糕,因为变量的内存是在应用程序启动时分配的,只有在应用程序结束时才会释放。它们被认为是错误的,因为它们可以从代码中的任何位置进行修改
当然,您使用静态方法来访问静态数据,但我建议您将静态数据设为私有,因此只有类本身可以通过静态方法修改数据。然后整个数据变为singleton
顺便说一下,你认为它是线程安全的,但你最好确保它是线程安全的。
关于通过实例调用静态方法。如果您需要其他任务的实例,那么这是有道理的,否则它会浪费很少的资源。除非某些开发人员将方法从静态更改为非静态或者添加具有相同名称和类似参数的非静态方法,否则没有错。从实例调用静态方法也会增加混淆,因为它不清楚该方法对类本身内的数据没有任何作用。