Tranh luận thân thiện với đồng nghiệp về điều này. Chúng tôi có một số suy nghĩ về điều này, nhưng tự hỏi đám đông SO nghĩ gì về điều này?
Tranh luận thân thiện với đồng nghiệp về điều này. Chúng tôi có một số suy nghĩ về điều này, nhưng tự hỏi đám đông SO nghĩ gì về điều này?
Câu trả lời:
Một lý do là không có hỗ trợ CLR cho địa phương chỉ đọc. Readonly được dịch sang mã opcode CLR / CLI initonly. Cờ này chỉ có thể được áp dụng cho các trường và không có ý nghĩa đối với một cục bộ. Trên thực tế, việc áp dụng nó cho một địa phương có thể sẽ tạo ra mã không thể xác minh được.
Điều này không có nghĩa là C # không thể làm điều này. Nhưng nó sẽ cung cấp hai ý nghĩa khác nhau cho cùng một cấu trúc ngôn ngữ. Phiên bản dành cho người dân địa phương sẽ không có ánh xạ tương đương CLR.
readonly
từ khóa cho các lĩnh vực cần phải được hỗ trợ bởi CLI vì ảnh hưởng của nó là có thể nhìn thấy hội đồng khác. Tất cả những gì nó sẽ có nghĩa là biến chỉ có một phép gán trong phương thức tại thời điểm biên dịch.
const
(trong C ++ giống C # readonly
hơn là C # const
, mặc dù nó có thể đóng cả hai vai trò). Tuy nhiên, C ++ hỗ trợ const
cho biến tự động cục bộ. Do đó, việc thiếu hỗ trợ CLR cho C # readonly
cho biến cục bộ là không thích hợp.
using
và out
đang làm chính xác điều đó và thế giới đã không sụp đổ.
Tôi nghĩ rằng đó là một đánh giá kém đối với các kiến trúc sư C #. sửa đổi chỉ đọc trên các biến cục bộ giúp duy trì tính đúng đắn của chương trình (giống như các xác nhận) và có thể giúp trình biên dịch tối ưu hóa mã (ít nhất là trong trường hợp của các ngôn ngữ khác). Thực tế là nó không được phép trong C # ngay bây giờ, là một lập luận khác cho rằng một số "tính năng" của C # chỉ là sự thực thi phong cách mã hóa cá nhân của người tạo ra nó.
Giải quyết câu trả lời của Jared, nó có thể chỉ phải là một tính năng thời gian biên dịch - trình biên dịch sẽ cấm bạn ghi vào biến sau khai báo ban đầu (sẽ phải bao gồm một phép gán).
Tôi có thể thấy giá trị trong điều này không? Có thể - nhưng không phải là nhiều, thành thật mà nói. Nếu bạn không thể dễ dàng biết liệu một biến có được gán ở nơi khác trong phương thức hay không, thì phương thức của bạn quá dài.
Đối với những gì nó có giá trị, Java có tính năng này (sử dụng final
modifier) và tôi đã rất hiếm khi nhìn thấy nó được sử dụng khác hơn trong trường hợp nó có được sử dụng để cho phép các biến để được chụp bởi một lớp bên trong vô danh - và nơi mà nó là được sử dụng, nó cho tôi ấn tượng về sự lộn xộn hơn là thông tin hữu ích.
readonly
/ final
giá trị từ các biến với từ khóa val
và var
từ khóa của nó . Trong mã Scala, các local val
được sử dụng rất thường xuyên (và trên thực tế, được ưu tiên hơn các local var
). Tôi nghi ngờ rằng các lý do chính khiến công cụ final
sửa đổi không được sử dụng thường xuyên hơn trong Java là a) lộn xộn và b) lười biếng.
readonly
sẽ không quá quan trọng. Mặt khác, đối với các biến cục bộ được sử dụng trong các bao đóng, readonly
trong nhiều trường hợp sẽ cho phép trình biên dịch tạo ra mã hiệu quả hơn. Hiện tại, khi việc thực thi nhập vào một khối chứa một bao đóng, trình biên dịch phải tạo một đối tượng đống mới cho các biến đóng lại, ngay cả khi không có mã nào sử dụng bao đóng được thực thi . Nếu một biến là chỉ đọc, mã bên ngoài bao đóng có thể sử dụng một biến bình thường; chỉ khi một đại biểu được tạo để đóng ...
Nhóm thiết kế C # 7 đã thảo luận ngắn gọn về một đề xuất chỉ người dân địa phương và các thông số . Từ Ghi chú cuộc họp thiết kế C # cho ngày 21 tháng 1 năm 2015 :
Các tham số và địa phương có thể được lambdas nắm bắt và do đó được truy cập đồng thời, nhưng không có cách nào để bảo vệ chúng khỏi các vấn đề trạng thái chia sẻ lẫn nhau: chúng không thể chỉ đọc được.
Nói chung, hầu hết các tham số và nhiều địa phương không bao giờ được chỉ định sau khi chúng nhận được giá trị ban đầu. Việc cho phép chúng chỉ đọc sẽ thể hiện rõ ràng ý định đó.
Một vấn đề là tính năng này có thể là một "sự phiền toái hấp dẫn". Trong khi "điều đúng đắn" cần làm gần như luôn luôn là tạo các tham số và local chỉ đọc, nó sẽ làm cho mã lộn xộn đáng kể để làm như vậy.
Một ý tưởng để giảm bớt phần nào điều này là cho phép tổ hợp chỉ đọc var trên một biến cục bộ được ký hợp đồng với val hoặc một cái gì đó ngắn gọn như vậy. Nói chung, chúng ta có thể cố gắng đơn giản nghĩ về một từ khóa ngắn hơn so với từ khóa chỉ đọc đã thiết lập để thể hiện tính chỉ đọc.
Thảo luận tiếp tục trong repo Thiết kế Ngôn ngữ C #. Bỏ phiếu để thể hiện sự ủng hộ của bạn. https://github.com/dotnet/csharplang/issues/188
Đó là một sự giám sát đối với nhà thiết kế ngôn ngữ c #. F # có từ khóa val và nó dựa trên CLR. Không có lý do gì C # không thể có tính năng ngôn ngữ giống nhau.
Tôi là đồng nghiệp đó và nó không thân thiện! (đùa thôi)
Tôi sẽ không loại bỏ tính năng này vì tốt hơn là viết các phương thức ngắn. Nó hơi giống như nói rằng bạn không nên sử dụng các chủ đề vì chúng khó. Đưa cho tôi con dao và để tôi chịu trách nhiệm không cắt chính mình.
Cá nhân tôi muốn một từ khóa loại "var" khác như "inv" (bất biến) hoặc "rvar" để tránh lộn xộn. Tôi đã nghiên cứu F # từ cuối năm nay và thấy điều bất biến hấp dẫn.
Không bao giờ biết Java có điều này.
Tôi muốn các biến chỉ đọc cục bộ theo cách tương tự như tôi muốn các biến const cục bộ. Nhưng nó có ít ưu tiên hơn các chủ đề khác.
Có thể ưu tiên của nó cũng là lý do khiến các nhà thiết kế C # chưa (chưa!) Triển khai tính năng này. Nhưng nó phải dễ dàng (và tương thích ngược) để hỗ trợ các biến chỉ đọc cục bộ trong các phiên bản sau.
Chỉ đọc có nghĩa là nơi duy nhất mà biến cá thể có thể được đặt là trong hàm tạo. Khi khai báo một biến cục bộ, nó không có một thể hiện (nó chỉ nằm trong phạm vi) và nó không thể bị phương thức khởi tạo chạm vào.
Tôi biết, điều này không trả lời lý do tại sao cho câu hỏi của bạn. Dù sao, những người đọc câu hỏi này có thể đánh giá cao đoạn mã bên dưới.
Nếu bạn thực sự lo lắng về việc tự đặt mình vào chân khi ghi đè một biến cục bộ chỉ nên được đặt một lần và bạn không muốn biến nó thành một biến có thể truy cập toàn cầu hơn, bạn có thể làm như thế này.
public class ReadOnly<T>
{
public T Value { get; private set; }
public ReadOnly(T pValue)
{
Value = pValue;
}
public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
{
if (object.ReferenceEquals(pReadOnlyT, null))
{
return object.ReferenceEquals(pT, null);
}
return (pReadOnlyT.Value.Equals(pT));
}
public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
{
return !(pReadOnlyT == pT);
}
}
Ví dụ sử dụng:
var rInt = new ReadOnly<int>(5);
if (rInt == 5)
{
//Int is 5 indeed
}
var copyValueOfInt = rInt.Value;
//rInt.Value = 6; //Doesn't compile, setter is private
Có thể không ít mã hơn rvar rInt = 5
nhưng nó hoạt động.
Bạn có thể khai báo các biến cục bộ chỉ đọc trong C #, nếu bạn đang sử dụng trình biên dịch tương tác C # csi
:
>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
Bạn cũng có thể khai báo các biến cục bộ chỉ đọc ở .csx
định dạng tập lệnh.
message
không phải là một biến ở đây, nó được biên dịch thành một trường. Đây không phải là nitpicking vì sự khác biệt rõ ràng cũng tồn tại trong C # tương tác: int x; Console.WriteLine(x)
là C # tương tác hợp pháp (vì x
là một trường và được khởi tạo ngầm) nhưng void foo() { int x; Console.WriteLine(x); }
không phải (vì x
là một biến và được sử dụng trước khi nó được gán). Ngoài ra, Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberType
sẽ tiết lộ rằng đó x
thực sự là một trường chứ không phải một biến cục bộ.
c # đã có một var chỉ đọc, mặc dù theo một cú pháp hơi khác:
Hãy xem xét những dòng sau:
var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;
So sánh với:
var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();
Phải thừa nhận rằng giải pháp đầu tiên có thể ít mã hơn để viết. Nhưng đoạn mã thứ 2 sẽ làm cho biến chỉ đọc rõ ràng, khi tham chiếu đến biến.
readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");
.
sử dụng const
từ khóa để làm cho biến chỉ đọc.
tham khảo: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
public class SealedTest
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}
const
đó biến chỉ có thể được chỉ định trong quá trình khởi tạo của nó — không phải kiểu csharp const
nơi chỉ có thể sử dụng các biểu thức thời gian biên dịch. Ví dụ: bạn không thể làm const object c = new object();
nhưng một readonly
địa phương sẽ cho phép bạn làm điều này.