Việc sử dụng biến static trong C # là gì? Khi nào sử dụng nó? Tại sao tôi không thể khai báo phương thức bên trong biến static?


106

Tôi đã tìm kiếm về các biến tĩnh trong C #, nhưng tôi vẫn chưa hiểu công dụng của nó. Ngoài ra, nếu tôi cố gắng khai báo biến bên trong phương thức, nó sẽ không cho tôi quyền thực hiện điều này. Tại sao?

Tôi đã xem một số ví dụ về các biến tĩnh. Tôi đã thấy rằng chúng ta không cần tạo một thể hiện của lớp để truy cập vào biến, nhưng điều đó là không đủ để hiểu công dụng của nó là gì và khi nào thì sử dụng.

Điều thứ hai

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
Có thể bạn có nghĩa là "trường tĩnh"?
Dennis

Giống như chúng tôi khai báo trong lớp static int i = 5
Kartik Patel

3
VB.NET hỗ trợ các biến tĩnh cục bộ. Họ phải triển khai nó để duy trì tương thích với vb. Số lượng mã mà nó tạo ra là rất lớn , tĩnh cục bộ rất khó vì chúng không an toàn cho chuỗi. Các trường cũng không an toàn cho chuỗi, nhưng mọi người đều mong đợi điều đó.
Hans Passant

Đừng quên đánh dấu câu trả lời là được chấp nhận nếu bạn có thông tin bạn muốn ...
Pranay Rana

3
Bạn có thể truy cập các biến / phương thức tĩnh thông qua kiểu (trong trường hợp này Book) không thông qua một instance ( book), vì vậy giải pháp dễ dàng hơn Book.myInt.
Jaider

Câu trả lời:


171

Một staticbiến chia sẻ giá trị của nó giữa tất cả các trường hợp của lớp.

Ví dụ mà không cần khai báo nó tĩnh:

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();
    }
}

Giải thích: Nếu bạn nhìn vào ví dụ trên, tôi chỉ khai báo intbiến. Khi tôi chạy mã này, đầu ra sẽ là 1010. Đơn giản của nó.

Bây giờ chúng ta hãy xem xét biến static ở đây; Tôi đang khai báo biến là a static.

Ví dụ với biến tĩnh:

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();
    }
}

Bây giờ khi tôi chạy mã trên, đầu ra sẽ là 1015. Vì vậy, giá trị biến tĩnh được chia sẻ giữa tất cả các trường hợp của lớp đó.


9
@Pranay: Vâng thats tốt hơn nhưng nếu bạn chỉ cho tôi ví dụ mà tôi thấy trên hơn cound được tốt hơn cho tôi và những người khác .... anyway nỗ lực tốt ....
Kartik Patel

1
Đó là tĩnh đến lớp, tức là giá trị của nó vẫn trung thành với các lớp học với giá trị của nó được lưu giữ trong nó ... chờ cho nó ... lớp
chwi

Bạn nói rằng một biến tĩnh được chia sẻ giữa tất cả các trường hợp của lớp ... nhưng nếu không có trường hợp nào thì sao? Bạn vẫn có thể đặt một biến? Nó có được phép lưu trữ dữ liệu động trong một lớp tĩnh không?
Kokodoko

@Kokodoko, ngay cả khi không có phiên bản nào, bạn chắc chắn có thể đặt biến. Điều đó xác định bản chất tĩnh của nó
Ladmerc

33

C # không có biến tĩnh nào cả. Bạn có thể khai báo trường tĩnh trong định nghĩa kiểu cụ thể thông qua C #. Trường tĩnh là một trạng thái, được chia sẻ với tất cả các trường hợp của loại cụ thể. Do đó, phạm vi của trường tĩnh là toàn bộ kiểu. Đó là lý do tại sao bạn không thể khai báo trường tĩnh trong một phương thức - bản thân phương thức là một phạm vi và các mục được khai báo trong một phương thức phải không thể truy cập được qua đường viền của phương thức.


5
Vâng, trong tài liệu, nó được nêu là "Một trường được khai báo với công cụ sửa đổi tĩnh được gọi là một biến tĩnh." msdn.microsoft.com/en-us/library/aa691162(v=vs.71).aspx Nhưng bạn đã đúng phần còn lại của lời giải thích.
Teoman shipahi

19

biến static được sử dụng khi chỉ cần một bản sao của biến. vì vậy nếu bạn khai báo biến bên trong phương thức thì không sử dụng biến như vậy, nó sẽ trở thành cục bộ chỉ hoạt động ..

ví dụ về tĩnh là

class myclass
{
    public static int a = 0;
}

Các biến được khai báo static thường được chia sẻ trên tất cả các trường hợp của một lớp.

Các biến được khai báo static thường được chia sẻ trên tất cả các trường hợp của một lớp. Khi bạn tạo nhiều phiên bản của lớp VariableTest Biến này vĩnh viễn được chia sẻ trên tất cả chúng. Do đó, tại bất kỳ thời điểm nhất định nào, sẽ chỉ có một giá trị chuỗi được chứa trong biến vĩnh viễn.

Vì chỉ có một bản sao của biến có sẵn cho tất cả các trường hợp, mã this.permament sẽ dẫn đến lỗi biên dịch vì có thể nhớ lại rằng this.variablename tham chiếu đến tên biến cá thể. Do đó, các biến tĩnh phải được truy cập trực tiếp, như được chỉ ra trong mã.


bạn có thể vui lòng giải thích với ví dụ?
Kartik Patel

nhưng nếu tôi tạo thể hiện của một lớp thì tôi không thể truy cập biến tĩnh. Tại sao? Tôi có thể truy cập biến tĩnh bằng classname.variable không chỉ bằng cách tạo thể hiện của một lớp .......... ......
Kartik Patel

@Kartik Patel vì bạn phải sử dụng tên lớp để truy cập myInt tĩnh. Tại sao nó như thế này, tôi không biết. Nhưng tôi muốn nói rằng nó rõ ràng hơn nhiều vì bạn muốn truy cập một phần tĩnh của lớp, nó không phải là tĩnh nếu bạn cần một thể hiện để truy cập nó.
khi

@dowhilefor: Nhưng như bạn đã đề cập ở trên rằng "Các biến được khai báo tĩnh thường được chia sẻ trên tất cả các trường hợp của một lớp." vậy thì ý nghĩa của điều này là gì?
Kartik Patel

@Kartik Patel bạn không thể truy cập biến từ bên ngoài bằng một thể hiện, nhưng bạn luôn có thể sử dụng biến tĩnh bên trong lớp của mình và sau đó nó được chia sẻ trên tất cả các trường hợp. Ngoài ra, không phải tôi là người đưa ra câu trả lời này, tôi chỉ bình luận về nó.
khi

9

Một số ví dụ "thế giới thực" cho các biến tĩnh:

xây dựng một lớp nơi bạn có thể đạt được các giá trị được mã hóa cứng cho ứng dụng của mình. Tương tự như kiểu liệt kê, nhưng với kiểu dữ liệu linh hoạt hơn.

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

Singleton được biết đến rộng rãi, điều này cho phép kiểm soát để có chính xác một thể hiện của một lớp. Điều này rất hữu ích nếu bạn muốn truy cập vào nó trong toàn bộ ứng dụng của mình, nhưng không phải chuyển nó cho mọi lớp chỉ để cho phép lớp này sử dụng nó.

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

        private static TextureManager sInstance = new TextureManager();

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

và đây là cách bạn sẽ gọi là thợ làm kết cấu

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

Về câu hỏi cuối cùng của bạn: Bạn đang tham khảo lỗi trình biên dịch CS0176 . Tôi đã cố gắng tìm thêm thông tin về điều đó, nhưng chỉ có thể tìm thấy những gì msdn phải nói về nó:

Một phương thức, trường, thuộc tính hoặc sự kiện tĩnh có thể được gọi trên một lớp ngay cả khi không có trường hợp nào của lớp đó được tạo. Nếu bất kỳ thể hiện nào của lớp được tạo, chúng không thể được sử dụng để truy cập thành viên tĩnh. Chỉ tồn tại một bản sao của các trường và sự kiện tĩnh, các phương thức và thuộc tính tĩnh chỉ có thể truy cập các trường tĩnh và sự kiện tĩnh.


5

Biến tĩnh được sử dụng khi chỉ cần một bản sao của nó. Hãy để tôi giải thích điều này bằng một ví dụ:

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);
    }
}

Bây giờ ở đây chúng tôi đã tạo 2 phiên bản cho classvòng kết nối của chúng tôi , tức là 2 bộ bản sao của _PI cùng với các biến khác được tạo. Vì vậy, giả sử nếu chúng ta có nhiều cá thể của lớp này, nhiều bản sao của _PIsẽ được tạo ra chiếm bộ nhớ. Vì vậy, trong những trường hợp như vậy, tốt hơn là tạo các biến như vậy _PI staticvà hoạt động trên chúng.

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);
    }
}

Bây giờ bất kể có bao nhiêu trường hợp được tạo cho classvòng tròn, chỉ có một bản sao tồn tại của biến _PItiết kiệm bộ nhớ của chúng ta.


4

Các lớp tĩnh không yêu cầu bạn tạo một đối tượng của lớp đó / khởi tạo chúng, bạn có thể đặt trước từ khóa C # static ở phía trước tên lớp để làm cho nó tĩnh.

Hãy nhớ rằng: chúng tôi không khởi tạo lớp Console, lớp String, Lớp mảng.

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();

    }
}

quan sát rất tốt vì nếu bạn cố gắng sử dụng đối tượng để truy cập giá trị của thuộc tính myInt the bạn sẽ gặp lỗi: static void Main () {Book book = new Book (); // điều này khiến bạn gặp lỗi: book.myInt = 5;
leonidaa

2

Bắt đầu từ ví dụ @Kartik Patel này, tôi đã thay đổi một chút có thể bây giờ rõ ràng hơn về biến tĩnh

 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. Biến lớp VS Biến phiên bản trong C #

    Thành viên lớp tĩnh C # HOẶC Biến lớp

    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();
    
        }
    
    
    }

    }

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

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

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

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

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

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


1

Các thành viên dữ liệu và các thành viên hàm hoạt động trên thể hiện của kiểu được gọi là thành viên thể hiện. Phương thức ToString của int (ví dụ) là ví dụ về các thành viên thể hiện. Theo mặc định, các thành viên là thành viên cá thể. Các thành viên dữ liệu và các thành viên hàm không hoạt động trên thể hiện của kiểu, mà trên chính kiểu, phải được đánh dấu là tĩnh. Phương thức Test.Main và Console.WriteLine là các phương thức tĩnh. Lớp Console thực sự là một lớp tĩnh, có nghĩa là tất cả các thành viên của nó là tĩnh. Bạn không bao giờ thực sự tạo các phiên bản của Bảng điều khiển — một bảng điều khiển được chia sẻ trên toàn bộ ứng dụng.


1

Để trả lời câu hỏi "khi nào thì sử dụng nó?" câu hỏi:

Tôi thường sử dụng một biến static (class) để gán một ID phiên bản duy nhất cho mọi phiên bản của một lớp. Tôi sử dụng cùng một mã trong mọi lớp, nó rất đơn giản:

//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();
//-----------------------------------------------------

Điều này minh họa một số điểm về các biến và phương thức tĩnh:

  1. Các biến và phương thức static được liên kết với lớp, không phải bất kỳ trường hợp cụ thể nào của lớp.
  2. Một phương thức tĩnh có thể được gọi trong phương thức khởi tạo của một cá thể - trong trường hợp này, phương thức tĩnh NextIID được sử dụng để khởi tạo thuộc tính chỉ đọc IID, là ID duy nhất cho trường hợp này.

Tôi thấy điều này hữu ích bởi vì tôi phát triển các ứng dụng trong đó nhiều đối tượng được sử dụng và thật tốt khi có thể theo dõi số lượng đã được tạo và theo dõi / truy vấn các trường hợp riêng lẻ.

Tôi cũng sử dụng các biến lớp để theo dõi những thứ như tổng và trung bình của các thuộc tính của các trường hợp có thể được báo cáo trong thời gian thực. Tôi nghĩ rằng lớp học là một nơi tốt để lưu giữ thông tin tóm tắt về tất cả các trường hợp của lớp.



0

Khi so sánh với các biến phiên, các biến tĩnh sẽ có cùng giá trị đối với tất cả người dùng xem xét tôi đang sử dụng một ứng dụng được triển khai trong máy chủ. Nếu hai người dùng truy cập cùng một trang của một ứng dụng thì biến tĩnh sẽ giữ giá trị mới nhất và cùng một giá trị sẽ được cung cấp cho cả hai người dùng, không giống như các biến phiên khác nhau cho mỗi người dùng. Vì vậy, nếu bạn muốn một cái gì đó chung và giống nhau cho tất cả người dùng bao gồm các giá trị được cho là được sử dụng dọc theo mã ứng dụng thì chỉ sử dụng tĩnh.


0

Bạn không cần phải khởi tạo một đối tượng, vì bạn sẽ sử dụng một biến tĩnh: Console.WriteLine (Book.myInt);


-1

Biến static giữ lại giá trị trước đó của nó cho đến khi chương trình thoát. Static được sử dụng bằng cách gọi trực tiếp class_Name.Method () hoặc class_Name.Property. Không cần tham chiếu đối tượng. Việc sử dụng static phổ biến nhất là lớp Math của C #. Math.Sin (), Math.Cos (), Math.Sqrt ().

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.