首先,静态关键字。
我在这里阅读了几篇关于static关键字的文章和过去的帖子。我没有找到许多我应该使用它的场景。我所知道的是它不会在堆上创建一个对象,它告诉我从性能的角度来看,对于一个经常使用的对象来说会很好。
还有其他理由使用它吗?
另外,我已经阅读了一些关于static关键字以及它不应该如何与实例变量一起使用或改变状态的内容。有人可以澄清一下吗?这似乎是2 + 2的情况,但我无法得到答案(缺少一些基本和简单的知识)。
最后,关于线程安全的话题,我应该在代码中查找什么来了解线程安全性?
我也在VB.NET中发布了这个,因为我认为不同的语言(C#/ VB.NET)会有不同的规则。
由于
答案 0 :(得分:4)
static关键字在C中表示不同的东西,但在C#和Java中,它声明方法和变量属于类而不是对象。
您可能希望将它用于不需要来自特定对象的任何数据的方法和变量,但对该类型的每个对象使用相同的数据。
例如,String.Format()是String类的静态方法。您可以在代码中调用它而无需创建String实例。同样,Math.Pi也是一个类变量。
但是像长度方法这样的东西没有任何意义,除非它作用于字符串的特定实例,因此它必须是一个实例方法。例如,x =“你好”.Length();
因此,如果您希望仅使用类名而不是对象调用方法,则可以创建静态方法。请注意,这样的方法只能引用静态变量并调用静态方法,因为它没有用于引用非静态成员的对象。
在C中,static关键字表示文件范围链接。顶级静态变量或函数的名称不会导出到其他编译对象代码。因此,两个文件可以声明相同名称的静态变量,而不会产生冲突。我们在C#中没有这个问题,因为有名称空间,私有,受保护和公共关键字来表示可见性。
另一个含义是C中函数内的静态变量。这些变量在函数调用之间保留它们的值。例如,您可以使用一个来计算调用函数的次数。 C#中的静态变量也有这个属性,但是你没有像在C中那样在方法中声明它们,只是在类中。
答案 1 :(得分:1)
最后,关于线程安全的话题,我应该在代码中查找什么来了解线程安全性?
编写线程安全的代码是一个非常重要的主题,我不会在这里讨论,但我会就静态和放大器的主题说一件事。线程安全。
确保代码按预期运行多个调用线程的大多数方法都涉及对对象实例的某种锁定。您会注意到在.NET框架(BCL)中,所有静态成员都是线程安全的。这是因为没有明确的方法可以知道对象的哪个实例应该被锁定,以便在所有可能的调用者之间共享该资源。
旧指南用于建议锁定类型本身,即:
lock (typeof(SomeType))
{
SomeType.SomeStaticMethod(...);
}
现在不鼓励使用这种方法,因为没有办法控制所有可想到的调用线程对这些锁定对象的访问顺序。锁定公共对象(包括ICollection.SyncRoot
,现在因同样的原因而被弃用)正在打开死锁的大门。在上面的例子中,类型实例是公开可用的,不应该被锁定。
鉴于没有单个实例静态方法的所有客户端可以合理地同意使用静态成员,Microsoft的BCL团队必须使所有静态成员都是类型安全的。值得庆幸的是,静态成员很少见。
答案 2 :(得分:0)
如果要存储每个实例唯一的东西,它应该是一个实例变量。如果您认为其他数据不是每个实例唯一(或者不需要创建实例),则可以将其他数据设置为静态数据。
e.g。 String.Empty(这是一个公共静态只读变量)。使用此功能不需要您创建新的字符串实例。
答案 3 :(得分:0)
我使用静态变量来保存从文件中读取的值(如sql查询),这些值将被称为很多函数(如在循环中)。每次调用函数时都避免碰到磁盘,并且很好地利用了“信息隐藏”。
答案 4 :(得分:0)
我认为这很好地回答了我的问题(涵盖了用法):
答案 5 :(得分:-1)
实际上静态变量不在堆栈中,它们保存在一个特殊的内存段中,既不是堆栈也不是堆栈。此外,变量是在堆上还是堆栈上都不会影响性能。
静态函数变量是函数中存在的变量,如果更改,则在调用之间保留其值。它们可以被视为按需初始化的全局值,只能在声明它们的函数中使用。 IMO没有充分的理由在函数中使用静态变量,除了偶尔的测试之外。
静态成员变量是类的所有实例之间共享的变量。因此,如果您的“Person”有一个名为“mCountry”的静态成员,那么所有人都将共享该变量。如果一个人改变它,它会改变每个人。静态成员很有用,因为它允许类的所有实例共享相同的数据,从而节省内存。
答案 6 :(得分:-1)
这是静态类变量的一个非常常见的用例:
public class Foo
{
private static Dictionary<string, Foo> Foos =
new Dictionary<string, Foo>();
public static Foo Create(string key)
{
if (Foos.ContainsKey(key)) return Foos[key];
Foos.Add(key, new Foo(key));
}
public string Key { get; set; }
private Foo(string key)
{
Key = key;
}
}
隐藏构造函数和集合允许类本身代理应用程序创建的所有Foo对象。