Trong .Net tại sao String.Empty chỉ đọc thay vì hằng số? Tôi chỉ tự hỏi liệu có ai biết lý do đằng sau quyết định đó không.
Trong .Net tại sao String.Empty chỉ đọc thay vì hằng số? Tôi chỉ tự hỏi liệu có ai biết lý do đằng sau quyết định đó không.
Câu trả lời:
Lý do static readonly
được sử dụng thay vì const
là do sử dụng với mã không được quản lý, như được Microsoft chỉ ra ở đây trong Bản phát hành cơ sở hạ tầng ngôn ngữ chung 2.0 . Các tập tin để xem xét là sscli20\clr\src\bcl\system\string.cs
.
Hằng số rỗng giữ giá trị chuỗi rỗng. Chúng ta cần gọi hàm tạo String để trình biên dịch không đánh dấu đây là chữ.
Đánh dấu điều này là một nghĩa đen có nghĩa là nó không hiển thị như một lĩnh vực mà chúng ta có thể truy cập từ bản địa.
Tôi tìm thấy thông tin này từ bài viết tiện dụng này tại CodeProject .
String.Empty
nữa vì lý do đó một mình.
Tôi nghĩ rằng có rất nhiều nhầm lẫn và phản ứng xấu ở đây.
Trước hết, const
các trường là static
thành viên ( không phải thành viên thể hiện ).
Kiểm tra phần 10.4 Các hằng số của đặc tả ngôn ngữ C #.
Mặc dù các hằng số được coi là thành viên tĩnh, một khai báo không đổi không yêu cầu cũng không cho phép sửa đổi tĩnh.
Nếu public const
các thành viên là tĩnh, người ta không thể xem xét rằng một hằng số sẽ tạo ra một Đối tượng mới.
Vì điều này, các dòng mã sau đây thực hiện chính xác điều tương tự đối với việc tạo ra một Đối tượng mới.
public static readonly string Empty = "";
public const string Empty = "";
Dưới đây là một lưu ý từ Microsoft giải thích sự khác biệt giữa 2:
Từ khóa chỉ đọc khác với từ khóa const. Một trường const chỉ có thể được khởi tạo tại phần khai báo của trường. Một trường chỉ đọc có thể được khởi tạo tại khai báo hoặc trong hàm tạo. Do đó, các trường chỉ đọc 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 trường const là hằng số thời gian biên dịch, trường chỉ đọc có thể được sử dụng cho hằng số thời gian chạy, ...
Vì vậy, tôi thấy rằng câu trả lời hợp lý duy nhất ở đây là của Jeff Yates.
const string
và static readonly string
làm điều tương tự. Các giá trị Const được thay thế trong mã được liên kết trong khi các giá trị chỉ đọc tĩnh được tham chiếu. Nếu bạn có const
thư viện A được thư viện B sử dụng, thư viện B sẽ thay thế tất cả các tham chiếu đến const
biến đó bằng giá trị bằng chữ của nó; nếu biến đó là static readonly
thay vào đó, nó sẽ được tham chiếu và giá trị của nó được xác định khi chạy.
String.Empty read only instead of a constant?
Nếu bạn tạo bất kỳ chuỗi nào không đổi , thì trình biên dịch sẽ được thay thế bằng chuỗi thực sự ở mọi nơi bạn gọi nó và bạn điền mã của mình với cùng một chuỗi và khi mã chạy cũng cần đọc lại chuỗi đó từ bộ nhớ khác dữ liệu.
Nếu bạn để chuỗi của bạn chỉ đọc ở một nơi vì nó là String.Empty
chương trình, thì chương trình chỉ giữ cùng một chuỗi ở một nơi và đọc nó hoặc tham chiếu đến nó - giữ dữ liệu trong bộ nhớ tối thiểu.
Ngoài ra nếu bạn biên dịch bất kỳ dll nào bằng String.Empty dưới dạng const và vì bất kỳ lý do nào thay đổi String.Empty, thì dll đã biên dịch sẽ không hoạt động giống nhau nữa, bởi vì cost
tạo mã bên trong để thực sự giữ một bản sao của chuỗi trên mỗi cuộc gọi.
Xem mã này ví dụ:
public class OneName
{
const string cConst = "constant string";
static string cStatic = "static string";
readonly string cReadOnly = "read only string";
protected void Fun()
{
string cAddThemAll ;
cAddThemAll = cConst;
cAddThemAll = cStatic ;
cAddThemAll = cReadOnly;
}
}
sẽ đến bởi trình biên dịch như:
public class OneName
{
// note that the const exist also here !
private const string cConst = "constant string";
private readonly string cReadOnly;
private static string cStatic;
static OneName()
{
cStatic = "static string";
}
public OneName()
{
this.cReadOnly = "read only string";
}
protected void Fun()
{
string cAddThemAll ;
// look here, will replace the const string everywhere is finds it.
cAddThemAll = "constant string";
cAddThemAll = cStatic;
// but the read only will only get it from "one place".
cAddThemAll = this.cReadOnly;
}
}
và cuộc gọi lắp ráp
cAddThemAll = cConst;
0000003e mov eax,dword ptr ds:[09379C0Ch]
00000044 mov dword ptr [ebp-44h],eax
cAddThemAll = cStatic ;
00000047 mov eax,dword ptr ds:[094E8C44h]
0000004c mov dword ptr [ebp-44h],eax
cAddThemAll = cReadOnly;
0000004f mov eax,dword ptr [ebp-3Ch]
00000052 mov eax,dword ptr [eax+0000017Ch]
00000058 mov dword ptr [ebp-44h],eax
Chỉnh sửa: Sửa lỗi chính tả
Câu trả lời này tồn tại cho mục đích lịch sử.
Nguyên văn:
Bởi vì String
là một lớp và do đó không thể là một hằng số.
Thảo luận mở rộng:
Rất nhiều hộp thoại hữu ích đã được bổ sung để xem xét câu trả lời này, và thay vì xóa nó, nội dung này được sao chép trực tiếp:
Trong .NET, chuỗi (không giống như trong Java) và Chuỗi hoàn toàn giống nhau. Và vâng, bạn có thể có các hằng chuỗi theo nghĩa đen trong .NET - DrJokepu ngày 3 tháng 2 '09 lúc 16:57
Bạn đang nói rằng một Class không thể có hằng số? - StingyJack ngày 3 tháng 2 'lúc 16:58
Có, các đối tượng phải sử dụng chỉ đọc. Chỉ structs có thể làm hằng số. Tôi nghĩ rằng khi bạn sử dụng
string
thay vìString
trình biên dịch sẽ thay đổi const thành chỉ đọc cho bạn. Tất cả để làm với việc giữ cho các lập trình viên C hạnh phúc. - Garry Shutler ngày 3 tháng 2 'lúc 16:59tvanfosson chỉ giải thích nó dài dòng hơn một chút. "X không thể là hằng số, vì chứa Y là một lớp" chỉ hơi quá bối cảnh;) - Leonidas ngày 3 tháng 2 '09 lúc 17:01
string.Empty là thuộc tính tĩnh trả về một thể hiện của lớp String, cụ thể là chuỗi rỗng, không phải chính lớp chuỗi. - tvanfosson 3 tháng 2 '09 lúc 17:01
Trống là một thể hiện chỉ đọc (nó không phải là một thuộc tính) của lớp String. - senfo 3 tháng 2 '09 lúc 17:02
Chấn thương đầu. Tôi vẫn nghĩ rằng tôi đúng, nhưng bây giờ tôi ít chắc chắn hơn. Nghiên cứu cần thiết tối nay! - Garry Shutler 3 tháng 2 'lúc 17:07
Chuỗi rỗng là một thể hiện của lớp chuỗi. Trống là trường tĩnh (không phải là thuộc tính, tôi đứng chính xác) trên lớp Chuỗi. Về cơ bản sự khác biệt giữa một con trỏ và điều nó trỏ đến. Nếu nó không chỉ đọc, chúng ta có thể thay đổi trường hợp nào mà trường rỗng đề cập đến. - tvanfosson ngày 3 tháng 2 'lúc 17:07
Garry, bạn không cần phải làm bất kỳ nghiên cứu. Hãy suy nghĩ về nó. Chuỗi là một lớp. Trống là một thể hiện của một chuỗi. - senfo 3 tháng 2 '09 lúc 17:12
Có một thứ tôi không hoàn toàn hiểu được: làm thế nào trên trái đất, hàm tạo tĩnh của lớp String có thể tạo một thể hiện của lớp String? Không phải đó là một loại kịch bản "gà hay trứng" sao? - DrJokepu 3 tháng 2 '09 lúc 17:12 5
Câu trả lời này sẽ đúng cho gần như bất kỳ lớp nào khác ngoài System.String. .NET thực hiện rất nhiều hiệu năng đặc biệt cho các chuỗi và một trong số đó là bạn CÓ THỂ có các hằng chuỗi, chỉ cần thử nó. Trong trường hợp này, Jeff Yates có câu trả lời đúng. - Joel Mueller 3 tháng 2 '09 lúc 19:25
Như được mô tả trong §7,18, một biểu thức hằng là một biểu thức có thể được đánh giá đầy đủ tại thời gian biên dịch. Vì cách duy nhất để tạo giá trị không null của loại tham chiếu khác với chuỗi là áp dụng toán tử mới và vì toán tử mới không được phép trong biểu thức không đổi, nên giá trị duy nhất có thể cho các hằng số loại tham chiếu khác với chuỗi là null. Hai bình luận trước được lấy trực tiếp từ đặc tả ngôn ngữ C # và nhắc lại những gì Joel Mueller đã đề cập. - senfo 4 tháng 2 '09 lúc 15:05 5