C#中静态变量的用途是什么?什么时候使用?为什么我不能在方法内部声明静态变量?


106

我已经在C#中搜索了静态变量,但是我仍然不了解它的用途。另外,如果我尝试在方法内部声明变量,则不会授予我执行此操作的权限。为什么?

我看过一些有关静态变量的例子。我已经看到我们不需要创建类的实例来访问变量,但这不足以了解其用途以及何时使用它。

第二件事

class Book
{
    public static int myInt = 0;
}

public class Exercise
{
    static void Main()
    {
        Book book = new Book();

        Console.WriteLine(book.myInt); // Shows error. Why does it show me error?
                                       // Can't I access the static variable 
                                       // by making the instance of a class?

        Console.ReadKey();
    }
}

4
您是说“静态场”吗?
丹尼斯

就像我们在类中声明static int i = 5
Kartik Patel 2012年

3
VB.NET支持局部静态变量。他们必须实现它才能与vb兼容。它生成的代码量很大,局部静态变量很困难,因为它们不是线程安全的。字段也不是线程安全的,但是每个人都希望这样做。
汉斯·帕桑

如果您得到了想要的信息,请不要忘记将答案标记为已接受...
Pranay Rana 2012年

3
您可以通过类型(在这种情况下Book)而不通过实例(book)访问静态变量/方法,因此更简单的解决方案是Book.myInt
Jaider 2015年

Answers:


171

一个static变量,股吧之类的所有实例中的价值。

没有声明为静态的示例:

public class Variable
{
    public int i = 5;
    public void test()
    {
        i = i + 5;
        Console.WriteLine(i);
    }
}


public class Exercise
{
    static void Main()
    {
        Variable var = new Variable();
        var.test();
        Variable var1 = new Variable();
        var1.test();
        Console.ReadKey();
    }
}

说明:如果您看上面的示例,我只声明int变量。当我运行此代码时,输​​出将为1010。这很简单。

现在让我们看一下这里的静态变量。我将变量声明为static

静态变量示例:

public class Variable
{
    public static int i = 5;
    public void test()
    {
        i = i + 5;
        Console.WriteLine(i);
    }
}


public class Exercise
{
    static void Main()
    {
        Variable var = new Variable();
        var.test();
        Variable var1 = new Variable();
        var1.test();
        Console.ReadKey();
    }
}

现在,当我运行以上代码时,输​​出将为1015。因此,静态变量值在该类的所有实例之间共享。


9
@Pranay:是的,这更好,但是如果您向我展示比我高的例子,对我和其他人来说都是更好的....无论如何都要努力....
Kartik Patel

1
它对班级是静态的,即,其值对班级保持忠实,并将其值存储在班级中……等待中……班级
chwi

您说静态变量在类的所有实例之间共享...但是如果没有实例怎么办?您还能设置一个变量吗?是否允许将动态数据存储在静态类中?
Kokodoko

@Kokodoko,即使没有实例,也可以设置该变量。这定义了它的静态性质
Ladmerc

33

C#根本没有静态变量。您可以通过C#在特定的类型定义中声明静态字段。静态字段是一种状态,与特定类型的所有实例共享。因此,静态字段的范围是整个类型。这就是为什么您不能在方法内声明静态字段的原因-方法本身就是作用域,并且方法中声明的项必须在方法的边界上不可访问。


5
好吧,在文档中它被声明为“用static修饰符声明的字段称为静态变量”。msdn.microsoft.com/zh-cn/library/aa691162(v=vs.71).aspx但是,您对其余的解释是正确的。
Teoman shipahi

19

当仅需要变量的一个副本时,将使用静态变量。因此,如果您在方法内部声明变量,则不会使用此类变量,它只会在局部起作用。

静态的例子是

class myclass
{
    public static int a = 0;
}

声明为静态的变量通常在类的所有实例之间共享。

声明为静态的变量通常在类的所有实例之间共享。当您创建VariableTest类的多个实例时,该变量永久对象将在所有实例之间共享。因此,在任何给定的时间点,永久变量中将只包含一个字符串值。

由于所有实例只有一个变量副本,因此代码this.permament将导致编译错误,因为可以回想this.variablename引用实例变量名称。因此,如代码中所示,将直接访问静态变量。


你能举例说明一下吗?
Kartik Patel 2012年

但是,如果我创建一个类的实例,那么我将无法访问静态变量。为什么? ......
卡蒂克·帕特尔

@Kartik Patel,因为您必须使用类名来访问静态myInt。为什么不这样呢,我不知道。但是我要说的是,它要清晰得多,因为您要访问类的静态部分,如果需要实例来访问它,则不是静态的。
dowhilefor 2012年

@dowhilefor:但是正如您前面提到的,“声明为静态的变量通常在类的所有实例之间共享”。那么这是什么意思呢?
Kartik Patel 2012年

@Kartik Patel,您无法从外部使用实例访问变量,但是您始终可以在类内部使用静态变量,然后在所有实例之间共享该变量。同样不是我给出这个答案,我只是在评论。
dowhilefor 2012年

9

静态变量的一些“真实世界”示例:

建立一个可以为您的应用程序获取硬编码值的类。与枚举类似,但在数据类型上具有更大的灵活性。

public static class Enemies
{
    public readonly static Guid Orc = new Guid("{937C145C-D432-4DE2-A08D-6AC6E7F2732C}");
}

众所周知的单例,这允许控制一个类的一个实例。如果要在整个应用程序中访问它,而不是仅将其传递给每个类以允许此类使用,则此功能非常有用。

public sealed class TextureManager
    {
        private TextureManager() {}
        public string LoadTexture(string aPath);

        private static TextureManager sInstance = new TextureManager();

        public static TextureManager Instance
        {
            get { return sInstance; }
        }
    }

这就是您所谓的texturemanager

TextureManager.Instance.LoadTexture("myImage.png");

关于最后一个问题:您正在引用编译器错误CS0176。我试图找到更多有关此的信息,但只能找到msdn关于它的内容:

即使没有创建该类的实例,也可以在该类上调用静态方法,字段,属性或事件。如果创建了该类的任何实例,则不能使用它们访问静态成员。仅存在静态字段和事件的一个副本,并且静态方法和属性只能访问静态字段和静态事件。


5

仅需要一个副本时,将使用静态变量。让我用一个例子解释一下:

class circle
{
    public float _PI =3.14F;
    public int Radius;

    public funtionArea(int radius)
    {
        return this.radius * this._PI      
    }
}
class program
{
    public static void main()
    {
        Circle c1 = new Cirle();
        float area1 = c1.functionRaduis(5);
        Circle c2 = new Cirle();
        float area2 = c1.functionRaduis(6);
    }
}

现在在这里,我们为class圆创建了2个实例,即创建了2套副本_PI 以及其他变量。可以说,如果我们有很多此类的实例,_PI则会创建多个副本,从而占用内存。因此,在这种情况下,最好使此类变量类似_PI static并对其进行操作。

class circle
{
    static float _PI =3.14F;
    public int Radius;

    public funtionArea(int radius)
    {
        return this.radius * Circle._PI      
    }
}
class program
{
    public static void main()
    {
        Circle c1 = new Cirle();
        float area1 = c1.functionRaduis(5);
        Circle c2 = new Cirle();
        float area2 = c1.functionRaduis(6);
    }
}

现在,无论为该class圆创建多少个实例,都仅存在一个变量副本,_PI从而节省了我们的内存。


4

静态类不需要您创建该类的对象/实例化它们,您可以在类名前面添加C#关键字static,以使其成为静态。

请记住:我们没有实例化Console类,String类,Array类。

class Book
{
    public static int myInt = 0;
}

public class Exercise
{
    static void Main()
    {
        Book book = new Book();
       //Use the class name directly to call the property myInt, 
      //don't use the object to access the value of property myInt

        Console.WriteLine(Book.myInt);

        Console.ReadKey();

    }
}

非常好的观察,因为如果尝试使用对象访问myInt属性的值,则会收到错误消息:static void Main(){Book book = new Book(); //这会给您错误:book.myInt = 5;
leonidaa '18

2

从@Kartik Patel示例开始,我做了一些更改,也许现在对静态变量更加清楚了

 public class Variable
    {
        public static string StaticName = "Sophia ";
        public string nonStName = "Jenna ";
        public void test()
        {
            StaticName = StaticName + " Lauren"; 
            Console.WriteLine("  static ={0}",StaticName);
            nonStName = nonStName + "Bean ";
            Console.WriteLine("  NeStatic neSt={0}", nonStName);

        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Variable var = new Variable();
            var.test();
            Variable var1 = new Variable();
            var1.test();
            Variable var2 = new Variable();
            var2.test();
            Console.ReadKey();

        }
    }

Output 
  static =Sophia  Lauren
  NeStatic neSt=Jenna Bean
  static =Sophia  Lauren Lauren
  NeStatic neSt=Jenna Bean
  static =Sophia  Lauren Lauren Lauren
  NeStatic neSt=Jenna Bean
  1. C#中的类变量VS实例变量

    静态类成员C#OR类变量

    class A
    {
        // Class variable or " static member variable"  are declared with 
        //the "static " keyword
    
        public static int i=20;
        public int j=10;         //Instance variable 
        public static string s1="static class variable"; //Class variable 
        public string s2="instance variable";        // instance variable 
    }
    class Program
    {
        static void Main(string[] args)
        {
            A obj1 = new A();
    
            // obj1 instance variables 
            Console.WriteLine("obj1 instance variables ");
            Console.WriteLine(A.i);
            Console.WriteLine(obj1.j);
            Console.WriteLine(obj1.s2);
            Console.WriteLine(A.s1);
    
            A obj2 = new A();
    
            // obj2 instance variables 
            Console.WriteLine("obj2 instance variables ");
            Console.WriteLine(A.i);
            Console.WriteLine(obj2.j);
            Console.WriteLine(obj2.s2);
            Console.WriteLine(A.s1);
    
            Console.ReadKey();
    
        }
    
    
    }

    }

在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明

https://zh.wikipedia.org/wiki/Class_variable

https://zh.wikipedia.org/wiki/Instance_variable

https://zh.wikipedia.org/wiki/Static_variable

https://javaconceptoftheday.com/class-variables-and-instance-variables-in-java/?fbclid=IwAR1_dtpHzg3bC5WlGQGdgewaTvuOI6cwVeFUtTV8IZuGTj1qH5PmKGwX0yM

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/classes-and-structs/static-classes-and-static-class-members


1

在类型的实例上进行操作的数据成员和函数成员称为实例成员。int的ToString方法(例如)是实例成员的示例。默认情况下,成员是实例成员。不对类型的实例而是对类型本身进行操作的数据成员和函数成员必须标记为静态。Test.Main和Console.WriteLine方法是静态方法。Console类实际上是一个静态类,这意味着其所有成员都是静态的。您实际上从未创建过控制台的实例-在整个应用程序中共享一个控制台。


1

回应“何时使用?” 题:

我经常使用静态(类)变量为类的每个实例分配唯一的实例ID。我在每个类中使用相同的代码,这非常简单:

//Instance ID ----------------------------------------
    // Class variable holding the last assigned IID
    private static int xID = 0;
    // Lock to make threadsafe (can omit if single-threaded)
    private static object xIDLock = new object();
    // Private class method to return the next unique IID 
    //  - accessible only to instances of the class
    private static int NextIID()                    
    {
        lock (xIDLock) { return ++xID; }
    }
    // Public class method to report the last IID used 
    // (i.e. the number of instances created)
    public static int LastIID() { return xID; }
    // Instance readonly property containing the unique instance ID
    public readonly int IID = NextIID();
//-----------------------------------------------------

这说明了有关静态变量和方法的两点:

  1. 静态变量和方法与该类相关联,而不与该类的任何特定实例相关联。
  2. 可以在实例的构造函数中调用静态方法-在这种情况下,静态方法NextIID用于初始化只读属性IID,该属性是该实例的唯一ID。

我发现这很有用,因为我开发了使用大量对象的应用程序,并且能够跟踪已创建的对象数量以及跟踪/查询单个实例是一件好事。

我还使用类变量来跟踪可实时报告的实例属性的总数和平均值之类的东西。我认为该类是保留有关该类所有实例的摘要信息的好地方。



0

与会话变量进行比较时,考虑到我正在使用服务器中部署的应用程序,静态变量对所有用户将具有相同的值。如果两个用户访问应用程序的同一页面,则静态变量将保存最新值,并且将向两个用户提供相同的值,这与会话变量不同,会话变量对于每个用户而言都是不同的。因此,如果您希望所有用户都拥有相同的东西,包括应该在应用程序代码中使用的值,则只能使用静态。



-1

静态变量将保留其先前的值,直到程序退出。通过直接调用class_Name.Method()或class_Name.Property使用静态方法。不需要对象引用。静态的最流行用法是C#的Math类。Math.Sin(),Math.Cos(),Math.Sqrt()。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.