Câu hỏi Tĩnh chỉ đọc so với const


Tôi đã đọc xung quanh const và static readonly lĩnh vực. Chúng tôi có một số lớp học chỉ chứa các giá trị không đổi. Được sử dụng cho nhiều thứ khác nhau trong hệ thống của chúng tôi. Vì vậy, tôi tự hỏi nếu quan sát của tôi là chính xác:

Những loại giá trị không đổi này luôn luôn là static readonly cho mọi thứ công khai? Và chỉ sử dụng const cho các giá trị nội bộ / được bảo vệ / riêng tư?

Bạn đề xuất món gì? Tôi có nên thậm chí không sử dụng static readonly lĩnh vực, nhưng thay vì sử dụng tài sản có thể?


1204
2018-04-16 11:21


gốc


Đây là một trường hợp rất thú vị mà tôi chỉ thấy có lợi cho static readonly: thử sử dụng một const bên trong một IEnumerator sẽ kích hoạt không thể thay đổi  yield và bạn sẽ gặp phải lỗi "Lỗi trình biên dịch nội bộ" đáng sợ. Tôi đã không kiểm tra mã bên ngoài Unity3D, nhưng tôi tin rằng đây là một trong hai mono hoặc là .MẠNG LƯỚI  lỗi. Nó là một c # vấn đề vẫn còn. - cregox
có thể trùng lặp Sự khác nhau giữa const và readonly là gì? - nawfal
sự khác biệt khác là bạn có thể sử dụng một chuỗi const trong một chuyển đổi, nhưng không phải là một chuỗi chỉ đọc tĩnh - flagg19
static readonly không thể được sử dụng trong switch-case tuyên bố là case biến, const là bắt buộc cho mục đích này. - mostafiz rahman
static readonly không thể được sử dụng làm thông số thuộc tính - Dread Boy


Các câu trả lời:


public static readonly các lĩnh vực có một chút khác thường; public static các thuộc tính (chỉ với một get) sẽ phổ biến hơn (có lẽ được ủng hộ bởi private static readonly cánh đồng).

const các giá trị được ghi trực tiếp vào trang gọi; đây là hai lưỡi:

  • nó là vô ích nếu giá trị được lấy vào thời gian chạy, có lẽ từ cấu hình
  • nếu bạn thay đổi giá trị của một const, bạn cần phải xây dựng lại tất cả các máy khách
  • nhưng nó có thể nhanh hơn, vì nó tránh được một cuộc gọi phương thức ...
  • ... đôi khi có thể đã được JIT gạch chân

Nếu giá trị sẽ không bao giờ thay đổi, sau đó const là tốt - Zero vv tạo ra các const hợp lý; p Khác hơn thế, static các thuộc tính phổ biến hơn.


830
2018-04-16 11:24



Tại sao một tài sản trên một lĩnh vực? Nếu đó là một lớp học bất biến, tôi thấy không có sự khác biệt. - Michael Hedgpeth
@ Michael - cùng lý do như mọi khi; nó ẩn thực hiện. Bạn có thể tìm thấy (sau này) rằng bạn cần phải được tải lười biếng, cấu hình dựa trên, một mặt tiền, hoặc bất cứ điều gì. Trong thực tế, hoặc thường sẽ ổn thôi ... - Marc Gravell♦
@CoffeeAddict theo định nghĩa, một hằng số không phải là kéo các giá trị từ tệp cấu hình; nó được đốt cháy như một chữ ở thời gian biên dịch. Cách duy nhất bạn có thể sử dụng một hằng số trong thời gian chạy là thông qua sự phản ánh trên các lĩnh vực. Bất kỳ lúc nào bạn cố gắng sử dụng nó, trình biên dịch như đãthay thế của bạn không thay đổi sử dụng cho theo nghĩa đen sử dụng; tức là nếu một phương thức trong mã của bạn sử dụng 6 hằng số và bạn kiểm tra nó là IL, sẽ không có đề cập đến bất kỳ lần tra cứu liên tục nào; các giá trị theo nghĩa đen sẽ được tải tại chỗ - Marc Gravell♦
@MarcGravell - THẬN TRỌNG: readonly các trường không thể được sử dụng trong các câu lệnh switch / case, thay vào đó bạn cần chúng const. - Luciano
@Luciano: Tôi hiểu ý của bạn bây giờ, bạn có thể bật các biến chỉ đọc, nhưng bạn không thể sử dụng biến chỉ đọc như trường hợp. điều đó có ý nghĩa, nhưng lúc đầu không rõ ràng chút nào. - MPavlak


tôi sẽ dùng static readonly nếu Khách hàng đang ở trong một hội đồng khác. Có const và Khách hàng trong hai hội đồng khác nhau là một cách hay để tự bắn mình vào chân.


200
2018-04-16 12:57



Vì vậy, tôi nghĩ như một số người đã đề cập hoặc ám chỉ, có thể là khôn ngoan khi chỉ sử dụng const cho các giá trị thực sự được biết đến hằng số nếu chúng được công khai nếu không chúng được dành riêng cho phạm vi truy cập nội bộ, được bảo vệ hoặc riêng tư. - jpierson
@Dio Lý do nó vẫn còn tồn tại là bởi vì nó không phải là một vấn đề cho mỗi se - đó là một cái gì đó để được nhận thức, nhưng khả năng nội tuyến consts trên ranh giới lắp ráp là một điều tốt cho hiệu suất. Nó thực sự chỉ là một vấn đề thực sự hiểu rằng "liên tục" có nghĩa là "nó sẽ không bao giờ thay đổi". - Michael Stum♦
@MichaelStum Ok Tôi không nên gọi nó là "một vấn đề". Trong dòng công việc của tôi, tôi có const và chia sẻ nó trên các hội đồng nhưng tôi biên dịch lại cho mỗi lần triển khai hoặc mã lô hàng. Tuy nhiên, thực tế này chắc chắn đáng để lưu ý về nó. - Dio Phung
Vì vậy, nói chung, internal const hoặc là public static readonly tùy thuộc vào khả năng hiển thị mong muốn. - Iiridayn
@Iiridayn Yeah, đó không phải là một cách xấu để nhìn vào nó. Có một số trường hợp cần xem xét (ví dụ: nếu sử dụng Phản chiếu hoặc nếu giá trị là cần thiết trên một thuộc tính) và có sử dụng hợp lệ cho public const (ví dụ: bất kỳ phần nào của tiêu chuẩn. Bất cứ khi nào tôi làm việc với XML, có một tệp không gian tên với một loạt public const string.) Nhưng về tổng thể, public const chỉ nên được sử dụng sau khi xem xét các tác động đúng cách. - Michael Stum♦


Một số thứ khác

const int a 

  • phải được khởi tạo
  • khởi tạo phải ở thời gian biên dịch

readonly int a

  • có thể sử dụng giá trị mặc định, không cần khởi tạo
  • khởi tạo có thể ở thời gian chạy

173
2018-04-16 11:36



trong ctor chỉ có. - Amit Kumar Ghosh


Đây chỉ là một bổ sung cho các câu trả lời khác. Tôi sẽ không lặp lại chúng (bây giờ là bốn năm sau).

Có những tình huống mà const và một phi-const có ngữ nghĩa khác nhau. Ví dụ:

const int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

in ra True, trong khi:

static readonly int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

viết False.

Lý do là phương pháp x.Equals có hai tình trạng quá tải, một quá tải short (System.Int16) và một object (System.Object). Bây giờ câu hỏi đặt ra là liệu một hoặc cả hai đều áp dụng với y tranh luận.

Khi nào y là hằng số biên dịch (theo nghĩa đen), const trường hợp, nó trở nên quan trọng là có tồn tại một chuyển đổi tiềm ẩn từ  int  đến  short miễn là int là một hằng số, và miễn là trình biên dịch C # xác minh rằng giá trị của nó nằm trong phạm vi của một short (mà 42 Là). Xem Chuyển đổi biểu thức liên tục ngầm định trong Đặc tả Ngôn ngữ C #. Vì vậy, cả hai quá tải phải được xem xét. Quá tải Equals(short) được ưa thích (bất kỳ short là một object, nhưng không phải tất cả object là short). Vì thế y được chuyển thành shortvà quá tải đó được sử dụng. Sau đó Equals so sánh hai short có giá trị giống hệt nhau và cung cấp true.

Khi nào y không phải là hằng số, không ngầm chuyển đổi từ int đến short tồn tại. Đó là bởi vì nói chung một intcó thể quá lớn để vừa với short. (An rõ ràng chuyển đổi không tồn tại, nhưng tôi không nói Equals((short)y)Vì vậy, điều đó không liên quan.) Chúng tôi thấy rằng chỉ có một quá tải áp dụng, Equals(object) một. Vì thế y được đóng hộp để object. Sau đó Equals sẽ so sánh một System.Int16 đến một System.Int32và vì các loại thời gian chạy thậm chí không đồng ý, điều đó sẽ mang lại false.

Chúng tôi kết luận rằng trong một số trường hợp (hiếm), thay đổi const nhập thành viên vào static readonly lĩnh vực (hoặc cách khác, khi có thể) có thể thay đổi hành vi của chương trình.


151
2017-09-11 14:52



Một bổ sung tốt cho câu trả lời được chấp nhận. Tôi muốn thêm rằng việc chuyển đổi thích hợp các kiểu dữ liệu và các nguyên tắc tương tự khác (như try catches vv) phải là một yếu tố chính của các lập trình viên có kinh nghiệm và không để lại cho trình biên dịch. Tuy nhiên, tôi đã học được điều gì đó mới mẻ từ đây. Cảm ơn bạn. - Uknight
Wow, tôi đã được lập trình trong C # trong một thời gian dài và tôi không bao giờ có thể đoán rằng một const int trong phạm vi của một đoạn ngắn có thể được chuyển đổi hoàn toàn thành một đoạn ngắn. Tôi phải nói đó là khá kỳ quặc. Tôi yêu C # nhưng những mâu thuẫn kỳ lạ mà dường như không thêm nhiều giá trị nhưng thêm rất nhiều sức mạnh não cần thiết để liên tục xem xét có thể gây phiền nhiễu, đặc biệt là cho người mới bắt đầu. - Mike Marynowski
@MikeMarynowski Đúng vậy. Nhưng tôi nghĩ họ đã đưa ra quy tắc đó (trong số các lý do khác) để đưa ra tuyên bố short x = 42; hợp pháp. Vì bạn có một int, cụ thể là chữ 42, hoàn toàn biến thành short x. Nhưng sau đó, họ có thể đã hạn chế điều này chỉ bằng chữ số; tuy nhiên, họ đã chọn cho phép những thứ như short x = y; Ở đâu y được định nghĩa là const int y = 42;, và sau đó họ đã kết thúc với điều này. - Jeppe Stig Nielsen


Một điều cần lưu ý là const được giới hạn trong các kiểu nguyên thủy / giá trị (ngoại lệ là chuỗi)


82
2018-04-16 11:28



Thực ra const cũng có thể được sử dụng cho các loại khác, ngoại trừ việc nó phải được khởi tạo thành null, làm cho nó vô dụng :) - nawfal
ngoại lệ như trong System.Exception? :) - Memet Olsen
@nawfal Chính xác hơn, chỉ loại giá trị mà const có thể được sử dụng, là sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, cộng với bất kỳ enum loại. const không thể được sử dụng cho các loại giá trị khác, như DateTime hoặc là TimeSpan hoặc là BigInteger. Nó cũng không thể được sử dụng cho IntPtr struct (được coi là kiểu "nguyên thủy" của một số; kiểu nguyên thủy hạn là khó hiểu trong C #). ↵↵ The const có thể được sử dụng cho tất cả loại tham chiếu. Nếu loại này là string, bất kỳ giá trị chuỗi nào cũng có thể được chỉ định. Nếu không, giá trị phải là null. - Jeppe Stig Nielsen
@JeppeStigNielsen - Tôi gần đây đã có một cuộc tranh luận với đầy tớ về điều này - anh ta chỉ ra rằng bạn có thể làm bất cứ điều gì (giá trị và loại tham chiếu) const sử dụng default. Dành cho struct các loại, đó là một cá thể với tất cả các thành viên của nó được đặt thành các giá trị mặc định. - Wai Ha Lee


Các readonly từ khóa khác với const từ khóa. A const trường chỉ có thể được khởi tạo tại khai báo của trường. A readonly trường có thể được khởi tạo hoặc tại khai báo hoặc trong một hàm tạo. Vì thế, readonly các trường có thể có các giá trị khác nhau tùy thuộc vào hàm tạo được sử dụng. Ngoài ra, trong khi const trường là hằng số biên dịch, readonly trường có thể được sử dụng cho hằng số thời gian chạy

Tham khảo MSDN ngắn và rõ ràng tại đây


23
2017-11-14 18:58





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

Không thay đổi : Theo mặc định static. Giá trị không thể thay đổi từ bất cứ đâu (Ctor, Function, runtime etc no-where).

Chỉ đọc : Giá trị có thể được thay đổi thông qua hàm tạo tại thời gian chạy. Nhưng không phải thông qua chức năng thành viên.

Bạn có thể xem qua repo của tôi: Các loại thuộc tính C #.


16
2018-01-12 17:14



Tin xấu ... liên kết bị hỏng! - Fer R
@ FerR có bạn đi: github.com/yeasin90/advanced-csharp/blob/master/CSharpAdvanced/… - Yeasin Abedin Siam