Sự khác biệt giữa const và chỉ đọc trong C # là gì?


1363

Sự khác biệt giữa constreadonlytrong C # là gì?

Khi nào bạn sẽ sử dụng cái này hơn cái kia?


Tôi đã phải xem qua một số câu trả lời để tìm liên kết này, nhưng đó là một câu trả lời hay. Eric Lippert đảm nhận tính bất biến trong C #
Frank Bryce

2
@donstack, thực sự theo tham chiếu C # , Trường chỉ đọc có thể được chỉ định và gán lại nhiều lần trong phần khai báo trường và hàm tạo.
Marques

Câu trả lời:


1289

Ngoài sự khác biệt rõ ràng của

  • phải khai báo giá trị tại thời điểm định nghĩa cho các giá trị constVS readonlycó thể được tính toán động nhưng cần được chỉ định trước khi hàm tạo thoát ra .. sau đó nó bị đóng băng.
  • 'const là ngầm static. Bạn sử dụng một ClassName.ConstantNameký hiệu để truy cập chúng.

Có một sự khác biệt tinh tế. Hãy xem xét một lớp được định nghĩa trong AssemblyA.

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyBtài liệu tham khảo AssemblyAvà sử dụng các giá trị này trong mã. Khi điều này được biên dịch,

  • trong trường hợp constgiá trị, nó giống như một tìm kiếm thay thế, giá trị 2 được 'nướng vào' AssemblyBIL. Điều này có nghĩa là nếu ngày mai tôi sẽ cập nhật I_CONST_VALUElên 20 trong tương lai. AssemblyBvẫn sẽ có 2 cho đến khi tôi biên dịch lại nó .
  • trong trường hợp readonlygiá trị, nó giống như một refvị trí bộ nhớ. Giá trị không được đưa vào AssemblyBIL. Điều này có nghĩa là nếu vị trí bộ nhớ được cập nhật, AssemblyBsẽ nhận được giá trị mới mà không cần biên dịch lại. Vì vậy, nếu I_RO_VALUEđược cập nhật lên 30, bạn chỉ cần xây dựng AssemblyA. Tất cả các khách hàng không cần phải biên dịch lại.

Vì vậy, nếu bạn tự tin rằng giá trị của hằng số sẽ không thay đổi, hãy sử dụng a const.

public const int CM_IN_A_METER = 100;

Nhưng nếu bạn có một hằng số có thể thay đổi (ví dụ độ chính xác) .. hoặc khi nghi ngờ, hãy sử dụng a readonly.

public readonly float PI = 3.14;

Cập nhật: Aku cần nhận được một đề cập vì anh ấy đã chỉ ra điều này trước tiên. Ngoài ra tôi cần phải cắm vào nơi tôi đã học được điều này .. C # hiệu quả - Bill Wagner


77
Các staticđiểm có vẻ là điểm quan trọng nhất và hữu ích -consts are implicitly static
LCJ

28
Phần về giá trị tham chiếu là phần quan trọng nhất. Giá trị Const có thể được tối ưu hóa đi.
CodingBarfield

22
readonlycác biến có thể được thay đổi bên ngoài hàm tạo (sự phản chiếu). Nó chỉ là trình biên dịch cố gắng cản trở bạn sửa đổi var bên ngoài hàm tạo.
Bitterblue

12
Các biến @ mini-me readonlykhông được phép thay đổi sau khi hàm tạo hoàn thành, thậm chí thông qua phản xạ. Thời gian chạy xảy ra để không thực thi điều này. Thời gian chạy cũng xảy ra không để thực thi mà bạn không thay đổi string.Emptyđến "Hello, world!", nhưng tôi vẫn sẽ không cho rằng điều này làm cho string.Emptysửa đổi, hoặc mã mà không nên cho rằng string.Emptysẽ luôn luôn là một chuỗi zero-length.

7
blog.msmvps.com/jonskeet/2014/07/16/ Đây là một chi tiết thú vị chỉ đọc chi phí đầu tư của chỉ đọc
CAD bloke

275

Có một gotcha với consts! Nếu bạn tham chiếu một hằng số từ một cụm khác, giá trị của nó sẽ được biên dịch ngay vào cụm gọi. Theo cách đó, khi bạn cập nhật hằng số trong cụm được tham chiếu, nó sẽ không thay đổi trong cụm gọi!


8
Khi dịch ngược (Reflector, ILSpy, ..), hằng số KHÔNG BAO GIỜ được tham chiếu bởi bất kỳ ai, bất kể cùng một hội đồng hay một hội đồng khác, vì vậy bạn không thể phân tích việc sử dụng một hằng số trong mã được biên dịch.
springy76

159

Hằng số

  • Các hằng số là tĩnh theo mặc định
  • Chúng phải có giá trị tại thời gian biên dịch (bạn có thể có ví dụ 3.14 * 2, nhưng không thể gọi phương thức)
  • Có thể được khai báo trong các hàm
  • Được sao chép vào mọi hội đồng sử dụng chúng (mọi hội đồng đều có một bản sao giá trị cục bộ)
  • Có thể được sử dụng trong các thuộc tính

Các trường chỉ đọc

  • Phải đặt giá trị, bằng cách thoát hàm tạo
  • Được đánh giá khi cá thể được tạo

Các trường chỉ đọc tĩnh

  • Được đánh giá khi thực thi mã chạm tham chiếu lớp (khi phiên bản mới được tạo hoặc phương thức tĩnh được thực thi)
  • Phải có một giá trị được đánh giá theo thời gian xây dựng tĩnh được thực hiện
  • Không nên đặt ThreadStaticAttribution trên các hàm này (các hàm tạo tĩnh sẽ chỉ được thực thi trong một luồng và sẽ đặt giá trị cho luồng của nó; tất cả các luồng khác sẽ có giá trị này chưa được khởi tạo)

58

Chỉ cần thêm, ReadOnly cho các loại tham chiếu chỉ làm cho tham chiếu chỉ đọc không phải là các giá trị. Ví dụ:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};

  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

Có loại tham chiếu nào khác stringmà bạn có thể sử dụng như một hằng số không?
springy76

Bạn có thể có constcác kiểu tham chiếu khác với chuỗi, nhưng hằng số chỉ có thể có giá trị null.
Mike Rosoft

40

Điều này giải thích nó . Tóm tắt: const phải được khởi tạo tại thời điểm khai báo, chỉ có thể được khởi tạo trên hàm tạo (và do đó có giá trị khác nhau tùy thuộc vào hàm tạo được sử dụng).

EDIT: Xem gotcha của Gishu ở trên để biết sự khác biệt tinh tế


32

const: Không thể thay đổi ở bất cứ đâu.

readonly: Giá trị này chỉ có thể được thay đổi trong hàm tạo. Không thể thay đổi trong các chức năng bình thường.


26

Có một gotcha nhỏ với chỉ đọc. Một trường chỉ đọc có thể được đặt nhiều lần trong (các) hàm tạo. Ngay cả khi giá trị được đặt trong hai hàm tạo chuỗi khác nhau, nó vẫn được phép.


public class Sample {
    private readonly string ro;

    public Sample() {
        ro = "set";
    }

    public Sample(string value) : this() {
        ro = value; // this works even though it was set in the no-arg ctor
    }
}

26

Một thành viên không đổi được định nghĩa tại thời gian biên dịch và không thể thay đổi khi chạy. Các hằng số được khai báo là một trường, sử dụng consttừ khóa và phải được khởi tạo khi chúng được khai báo.

public class MyClass
{
    public const double PI1 = 3.14159;
}

Một readonlythành viên giống như một hằng số ở chỗ nó đại diện cho một giá trị không thay đổi. Sự khác biệt là một readonlythành viên có thể được khởi tạo trong thời gian chạy, trong một hàm tạo, cũng như có thể được khởi tạo khi chúng được khai báo.

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

hăng sô

  • Chúng không thể được khai báo là static(chúng hoàn toàn tĩnh)
  • Giá trị của hằng được đánh giá tại thời gian biên dịch
  • hằng số chỉ được khởi tạo lúc khai báo

chỉ đọc

  • Chúng có thể là mức cá thể hoặc mức tĩnh
  • Giá trị được đánh giá trong thời gian chạy
  • chỉ đọc có thể được khởi tạo trong khai báo hoặc bằng mã trong hàm tạo

6
Họ không thể tĩnh , họ tĩnh. Bạn nên làm rõ nếu bạn có nghĩa là người ta không thể tuyên bốstatic const int i = 0;
nawfal

Bạn có thể giải thích tại sao constkhai báo không thể được thực hiện bên trong các phương thức?
Minh Trần

21

Một const là hằng số thời gian biên dịch trong khi chỉ đọc cho phép một giá trị được tính tại thời gian chạy và được đặt trong hàm tạo hoặc trình khởi tạo trường. Vì vậy, một 'const' luôn luôn không đổi nhưng 'chỉ đọc' chỉ đọc khi được gán.

Eric Lippert của nhóm C # có thêm thông tin về các loại bất biến khác nhau


15

Đây là một liên kết khác chứng minh làm thế nào const không phải là phiên bản an toàn hoặc có liên quan cho các loại tham chiếu.

Tóm tắt :

  • Giá trị thuộc tính const của bạn được đặt tại thời gian biên dịch và không thể thay đổi khi chạy
  • Const không thể được đánh dấu là tĩnh - từ khóa biểu thị chúng là tĩnh, không giống như các trường chỉ đọc có thể.
  • Không thể là bất cứ thứ gì ngoại trừ các loại giá trị (nguyên thủy)
  • Từ khóa chỉ đọc đánh dấu trường là không thể thay đổi. Tuy nhiên, thuộc tính có thể được thay đổi bên trong hàm tạo của lớp
  • Từ khóa chỉ đọc cũng có thể được kết hợp với tĩnh để làm cho nó hoạt động theo cách tương tự như một const (ít nhất trên bề mặt). Có một sự khác biệt rõ rệt khi bạn nhìn vào IL giữa hai
  • các trường const được đánh dấu là "nghĩa đen" trong IL trong khi chỉ đọc là "initonly"

11

Chỉ đọc : Giá trị có thể được thay đổi thông qua Ctor khi chạy. Nhưng không thông qua chức năng thành viên

Hằng : Bằng cách bất chấp tĩnh. Giá trị không thể thay đổi từ bất cứ đâu (Ctor, Function, runtime v.v.


cảm ơn vì đã không bắt tôi đọc 4 đoạn chỉ cho hai lần đi này ...
Don Cheadle


6

Tôi tin rằng một constgiá trị là giống nhau cho tất cả các đối tượng (và phải được khởi tạo bằng biểu thức bằng chữ), trong khi readonlycó thể khác nhau cho mỗi lần khởi tạo ...


5

Một trong các thành viên trong văn phòng của chúng tôi đã cung cấp hướng dẫn sau đây về thời điểm sử dụng const, tĩnh và chỉ đọc:

  • Sử dụng const khi bạn có một biến loại mà bạn có thể biết trong thời gian chạy (chuỗi ký tự, int, double, enums, ...) mà bạn muốn tất cả các thể hiện hoặc người tiêu dùng của một lớp có quyền truy cập vào nơi giá trị không nên thay đổi.
  • Sử dụng tĩnh khi bạn có dữ liệu mà bạn muốn tất cả các phiên bản hoặc người tiêu dùng của một lớp có quyền truy cập vào nơi giá trị có thể thay đổi.
  • Sử dụng tĩnh chỉ đọc khi bạn có một biến loại mà bạn không thể biết trong thời gian chạy (đối tượng) mà bạn muốn tất cả các thể hiện hoặc người tiêu dùng của một lớp có quyền truy cập vào nơi giá trị không nên thay đổi.
  • Sử dụng chỉ đọc khi bạn có một biến cấp độ cá thể, bạn sẽ biết tại thời điểm tạo đối tượng không nên thay đổi.

Một lưu ý cuối cùng: một trường const là tĩnh, nhưng nghịch đảo là không đúng.


1
Tôi nghĩ bạn có nghĩa là "trò chuyện." Nghịch đảo sẽ là "một trường không hằng không tĩnh." Mà có thể đúng hoặc không đúng. Điều ngược lại, "một trường tĩnh là (luôn luôn) const" là không đúng.
Michael Blackburn

5

Cả hai đều là hằng số, nhưng một const cũng có sẵn tại thời gian biên dịch. Điều này có nghĩa là một khía cạnh của sự khác biệt là bạn có thể sử dụng các biến const làm đầu vào cho các hàm tạo thuộc tính, nhưng không phải là các biến chỉ đọc.

Thí dụ:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}

public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }

  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}

5
  • khi nào sử dụng consthoặcreadonly

    • const

      • hằng số thời gian biên dịch : hằng số tuyệt đối , giá trị được đặt trong khi khai báo, nằm trong chính mã IL
    • readonly

      • hằng số thời gian chạy : có thể được đặt trong hàm tạo / init thông qua tệp cấu hình App.config, nhưng một khi nó khởi chạy thì không thể thay đổi

4

Các biến được đánh dấu const ít hơn một chút so với các macro #define được gõ mạnh, tại thời điểm biên dịch các tham chiếu biến const được thay thế bằng các giá trị bằng chữ. Kết quả là chỉ có các loại giá trị nguyên thủy tích hợp nhất định có thể được sử dụng theo cách này. Các biến được đánh dấu chỉ đọc có thể được đặt, trong một hàm tạo, tại thời gian chạy và tính năng chỉ đọc của chúng cũng được thực thi trong thời gian chạy. Có một số chi phí hiệu suất nhỏ liên quan đến điều này nhưng điều đó có nghĩa là bạn có thể sử dụng chỉ đọc với bất kỳ loại nào (ngay cả các loại tham chiếu).

Ngoài ra, các biến const vốn là tĩnh, trong khi các biến chỉ đọc có thể là trường hợp cụ thể nếu muốn.


Đã thêm rằng consts được gõ mạnh #define macro. Nếu không, chúng tôi có thể khiến tất cả những người C hoặc C ++ sợ hãi. :-)
Jason Baker

4

HĂNG SÔ

  1. từ khóa const có thể được áp dụng cho các trường hoặc các biến cục bộ
  2. Chúng ta phải gán trường const tại thời điểm khai báo
  3. Không phân bổ bộ nhớ Vì giá trị const được nhúng trong chính mã IL sau khi biên dịch. Nó giống như tìm tất cả các lần xuất hiện của biến const và thay thế bằng giá trị của nó. Vì vậy, mã IL sau khi biên dịch sẽ có các giá trị được mã hóa cứng thay cho các biến const
  4. Const trong C # theo mặc định là tĩnh.
  5. Giá trị là hằng số cho tất cả các đối tượng
  6. Có vấn đề về phiên bản dll - Điều này có nghĩa là bất cứ khi nào chúng ta thay đổi một biến const hoặc thuộc tính công khai, (trên thực tế, nó không được thay đổi về mặt lý thuyết), bất kỳ dll hoặc lắp ráp nào sử dụng biến này phải được xây dựng lại
  7. Chỉ các kiểu dựng sẵn C # có thể được khai báo là hằng số
  8. Không thể truyền trường Const dưới dạng tham số ref hoặc out

Chỉ đọc

  1. từ khóa chỉ đọc chỉ áp dụng cho các trường không phải là biến cục bộ
  2. Chúng ta có thể gán trường chỉ đọc tại thời điểm khai báo hoặc trong hàm tạo, không phải trong bất kỳ phương thức nào khác.
  3. bộ nhớ động được phân bổ cho các trường chỉ đọc và chúng ta có thể nhận được giá trị trong thời gian chạy.
  4. Readonly thuộc về đối tượng được tạo nên chỉ được truy cập thông qua thể hiện của lớp. Để làm cho nó thành viên lớp, chúng ta cần thêm từ khóa tĩnh trước khi chỉ đọc.
  5. Giá trị có thể khác nhau tùy theo hàm tạo được sử dụng (vì nó thuộc về đối tượng của lớp)
  6. Nếu bạn khai báo một kiểu không nguyên thủy (kiểu tham chiếu) là tham chiếu chỉ đọc là bất biến không phải là đối tượng mà nó chứa.
  7. Vì giá trị thu được trong thời gian chạy, không có vấn đề phiên bản dll với các trường / thuộc tính chỉ đọc.
  8. Chúng ta có thể chuyển trường chỉ đọc dưới dạng tham số ref hoặc out trong ngữ cảnh của hàm tạo.

3

Một Gotcha khác .

Vì const thực sự chỉ hoạt động với các kiểu dữ liệu cơ bản, nên nếu bạn muốn làm việc với một lớp, bạn có thể cảm thấy "bị ép buộc" sử dụng ReadOnly. Tuy nhiên, hãy cẩn thận với cái bẫy! ReadOnly có nghĩa là bạn không thể thay thế đối tượng bằng một đối tượng khác (bạn không thể làm cho nó tham chiếu đến một đối tượng khác). Nhưng bất kỳ quá trình nào có tham chiếu đến đối tượng đều được tự do sửa đổi các giá trị bên trong đối tượng!

Vì vậy, đừng nhầm lẫn khi nghĩ rằng ReadOnly ngụ ý người dùng không thể thay đổi mọi thứ. Không có cú pháp đơn giản nào trong C # để ngăn việc khởi tạo một lớp thay đổi giá trị bên trong của nó (theo như tôi biết).


Vâng, đó là nhiều hơn một chủ đề chung. Nếu bạn có một thuộc tính chỉ hiển thị danh sách mảng, bạn vẫn có thể sửa đổi danh sách mảng. Bạn không thể đặt một danh sách mảng khác cho thuộc tính đó, nhưng bạn không thể ngăn người dùng thay đổi danh sách mảng.
Gishu

3

A constphải được mã hóa cứng , trong đó readonlycó thể được đặt trong hàm tạo của lớp.


3

Có sự khác biệt đáng chú ý giữa các trường const và chỉ đọc trong C # .Net

const theo mặc định là tĩnh và cần được khởi tạo với giá trị không đổi, không thể sửa đổi sau này. Thay đổi giá trị cũng không được phép trong các nhà xây dựng. Nó không thể được sử dụng với tất cả các kiểu dữ liệu. Ví dụ: DateTime. Nó không thể được sử dụng với kiểu dữ liệu DateTime.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

chỉ đọc có thể được khai báo là tĩnh, nhưng không cần thiết. Không cần phải khởi tạo tại thời điểm khai báo. Giá trị của nó có thể được gán hoặc thay đổi bằng cách sử dụng hàm tạo. Vì vậy, nó mang lại lợi thế khi được sử dụng làm thành viên lớp thể hiện. Hai khởi tạo khác nhau có thể có giá trị khác nhau của trường chỉ đọc. Dành cho người cũ

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Sau đó, trường chỉ đọc có thể được khởi tạo với các giá trị cụ thể ngay lập tức, như sau:

A objOne = new A(5);
A objTwo = new A(10);

Ở đây, ví dụ objOne sẽ có giá trị của trường chỉ đọc là 5 và objTwo có 10. Không thể sử dụng const.


2

Một hằng số sẽ được biên dịch vào người tiêu dùng dưới dạng giá trị bằng chữ trong khi chuỗi tĩnh sẽ đóng vai trò tham chiếu đến giá trị được xác định.

Như một bài tập, hãy thử tạo thư viện bên ngoài và sử dụng nó trong ứng dụng bảng điều khiển, sau đó thay đổi các giá trị trong thư viện và biên dịch lại (không biên dịch lại chương trình tiêu dùng), thả DLL vào thư mục và chạy EXE theo cách thủ công, bạn nên tìm chuỗi không đổi không thay đổi.


Tôi thực sự nghi ngờ đó là sự thật ... Tôi sẽ đi kiểm tra.
ljs

đây là một trong 50 cách cụ thể để cải thiện của bạn C # - amazon.co.uk/Effective-Specific-Ways-Improve-Your/dp/0321245660/...
Russ Cam


@Andrew Hare - vâng, tôi vừa kiểm tra. Tôi rất ngạc nhiên, đó là một gotcha thực sự, tôi thực sự rất ngạc nhiên về điều đó, thật ngạc nhiên đó là trường hợp ...!
ljs

Tôi làm đối tượng, tuy nhiên, việc sử dụng con trỏ từ ở đây. Nó không phải là một con trỏ, đó là một tài liệu tham khảo, và có một sự khác biệt trong C # như bạn có thể thao tác con trỏ không được quản lý trong chế độ không an toàn nên điều quan trọng là phải phân biệt giữa hai người.
ljs

2

Không thay đổi

Chúng ta cần cung cấp giá trị cho trường const khi nó được xác định. Trình biên dịch sau đó lưu giá trị của hằng trong siêu dữ liệu của tổ hợp. Điều này có nghĩa là một hằng số chỉ có thể được định nghĩa cho kiểu nguyên thủy như boolean, char, byte, v.v. Các hằng số luôn được coi là thành viên tĩnh, không phải thành viên thể hiện.

Chỉ đọc

Các trường chỉ đọc chỉ có thể được giải quyết trong thời gian chạy. Điều đó có nghĩa là chúng ta có thể định nghĩa một giá trị cho một giá trị bằng cách sử dụng hàm tạo cho kiểu mà trường được khai báo. Việc xác minh được thực hiện bởi trình biên dịch rằng các trường chỉ đọc không được ghi bởi bất kỳ phương thức nào khác ngoài hàm tạo.

Thông tin thêm về cả hai được giải thích ở đây trong bài viết này


1

Chủ yếu; bạn có thể gán một giá trị cho trường chỉ đọc tĩnh thành giá trị không cố định trong thời gian chạy, trong khi một const phải được gán một giá trị không đổi.


1

Const và readonly tương tự nhau, nhưng chúng không hoàn toàn giống nhau. Trường const là hằng số thời gian biên dịch, nghĩa là giá trị đó có thể được tính tại thời gian biên dịch. Trường chỉ đọc cho phép các kịch bản bổ sung trong đó một số mã phải được chạy trong khi xây dựng loại. Sau khi xây dựng, một trường chỉ đọc có thể được thay đổi.

Chẳng hạn, các thành viên const có thể được sử dụng để xác định các thành viên như:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

vì các giá trị như 3.14 và 0 là các hằng số thời gian biên dịch. Tuy nhiên, hãy xem xét trường hợp bạn xác định một loại và muốn cung cấp một số phiên bản pre-fab của loại đó. Ví dụ, bạn có thể muốn xác định lớp Màu và cung cấp "hằng số" cho các màu phổ biến như Đen, Trắng, v.v. Không thể làm điều này với các thành viên const, vì phía bên tay phải không phải là hằng số thời gian biên dịch. Người ta có thể làm điều này với các thành viên tĩnh thông thường:

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

nhưng sau đó, không có gì để giữ cho khách hàng của Color không bị làm phiền với nó, có lẽ bằng cách hoán đổi các giá trị Đen và Trắng. Không cần phải nói, điều này sẽ gây ra sự bối rối cho các khách hàng khác của lớp Màu. Tính năng "chỉ đọc" giải quyết tình huống này. Bằng cách đơn giản là giới thiệu từ khóa chỉ đọc trong các khai báo, chúng tôi duy trì việc khởi tạo linh hoạt trong khi ngăn chặn mã máy khách khỏi bị lừa đảo.

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

Thật thú vị khi lưu ý rằng các thành viên const luôn tĩnh, trong khi một thành viên chỉ đọc có thể là tĩnh hoặc không, giống như một trường thông thường.

Có thể sử dụng một từ khóa duy nhất cho hai mục đích này, nhưng điều này dẫn đến các vấn đề về phiên bản hoặc vấn đề về hiệu suất. Giả sử trong một khoảnh khắc chúng tôi đã sử dụng một từ khóa duy nhất cho (const) này và một nhà phát triển đã viết:

public class A
{
    public static const C = 0;
}

và một nhà phát triển khác đã viết mã dựa trên A:

public class B
{
    static void Main() {
        Console.WriteLine(A.C);
    }
}

Bây giờ, mã được tạo có thể dựa vào thực tế rằng AC là hằng số thời gian biên dịch không? Tức là, việc sử dụng AC có thể được thay thế bằng giá trị 0 không? Nếu bạn nói "có" với điều này, thì điều đó có nghĩa là nhà phát triển của A không thể thay đổi cách khởi tạo AC - điều này ràng buộc tay của nhà phát triển A mà không được phép. Nếu bạn nói "không" với câu hỏi này thì việc tối ưu hóa quan trọng sẽ bị bỏ qua. Có lẽ tác giả của A tích cực rằng AC sẽ luôn bằng không. Việc sử dụng cả const và readonly cho phép nhà phát triển của A chỉ định ý định. Điều này làm cho hành vi phiên bản tốt hơn và hiệu suất tốt hơn.


1

ReadOnly: Giá trị sẽ chỉ được khởi tạo một lần từ hàm tạo của lớp.
const: có thể được khởi tạo trong bất kỳ chức năng nào nhưng chỉ một lần


1

Sự khác biệt là giá trị của trường chỉ đọc tĩnh được đặt tại thời gian chạy, do đó, nó có thể có giá trị khác nhau cho các lần thực hiện khác nhau của chương trình. Tuy nhiên, giá trị của trường const được đặt thành hằng số thời gian biên dịch.

Ghi nhớ: Đối với các loại tham chiếu, trong cả hai trường hợp (tĩnh và thể hiện), công cụ sửa đổi chỉ đọc chỉ ngăn bạn gán một tham chiếu mới cho trường. Nó đặc biệt không làm cho đối tượng được chỉ ra bởi tham chiếu.

Để biết chi tiết, vui lòng tham khảo C # Câu hỏi thường gặp về chủ đề này: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx


1

Các biến không đổi được khai báo và khởi tạo tại thời điểm biên dịch. Giá trị không thể thay đổi sau khi phường. Các biến chỉ đọc sẽ chỉ được khởi tạo từ hàm tạo tĩnh của lớp. Chỉ đọc chỉ được sử dụng khi chúng ta muốn gán giá trị trong thời gian chạy.


1

Const : Giá trị không đổi tuyệt đối trong suốt thời gian sử dụng.

Chỉ đọc : Nó có thể được thay đổi trong thời gian chạy.


1
Định nghĩa của bạn về 'Chỉ đọc' mà nó có thể thay đổi là thiếu sót. Tôi đoán bằng 'thay đổi' bạn có nghĩa là 'thiết lập', như 'nó có thể được đặt trong thời gian chạy'.
Ahmed

0

Một điều để thêm vào những gì mọi người đã nói ở trên. Nếu bạn có một hội đồng chứa giá trị chỉ đọc (ví dụ: chỉ đọc MaxFooCount = 4;), bạn có thể thay đổi giá trị mà các hội đồng gọi thấy bằng cách vận chuyển một phiên bản mới của hội đồng đó với một giá trị khác (ví dụ: chỉ đọc MaxFooCount = 5;)

Nhưng với một hằng số, nó sẽ được gấp lại thành mã của người gọi khi người gọi được biên dịch.

Nếu bạn đã đạt đến mức độ thành thạo C # này, bạn đã sẵn sàng cho cuốn sách của Bill Wagner, C # hiệu quả: 50 cách cụ thể để cải thiện C # của bạn Trả lời chi tiết câu hỏi này, và 49 điều khác).

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.