Câu hỏi Hai dấu hỏi có ý nghĩa gì với nhau trong C #?


Đã chạy qua dòng mã này:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

Hai dấu hỏi có ý nghĩa gì, đó có phải là một loại toán tử bậc ba nào đó không? Thật khó để tìm kiếm trong Google.


1322
2018-01-15 14:03


gốc


Nó chắc chắn không phải một toán tử bậc ba - nó chỉ có hai toán hạng! Nó giống như toán tử có điều kiện (mà Là ternary) nhưng toán tử kết hợp null là toán tử nhị phân. - Jon Skeet
Tôi đã giải thích nó trong một cuộc phỏng vấn mà trước đây người sử dụng lao động tiềm năng đã bày tỏ nghi ngờ về khả năng C # của tôi, vì tôi đã sử dụng Java một cách chuyên nghiệp trong một thời gian trước đó. Họ đã không nghe nói về nó trước đây, và không hỏi câu hỏi của tôi với C # sau đó :) - Jon Skeet
@Jon Skeet Đã không có một sử thi như vậy không nhận ra kỹ năng kể từ khi anh chàng từ chối The Beatles. :-) Từ bây giờ chỉ cần gửi cho họ một bản sao của cuốn sách của bạn với một liên kết url đến hồ sơ SO của bạn được viết trên bìa bên trong. - Iain Holder
IainMH: Đối với những gì nó có giá trị, tôi đã không khá bắt đầu viết cuốn sách. (Hoặc có lẽ tôi chỉ đang làm việc trên chương 1 - một cái gì đó như thế.) Phải thừa nhận rằng một tìm kiếm cho tôi sẽ nhanh chóng tìm thấy blog của tôi + bài viết, v.v. - Jon Skeet
Re: câu cuối cùng trong q - cho ref trong tương lai, SymbolHound là tuyệt vời cho loại điều, ví dụ symbolhound.com/?q=%3F%3F&l=&e=&n=&u= [với bất kỳ ai đáng ngờ - tôi không liên kết theo bất kỳ cách nào, giống như một công cụ tốt khi tôi tìm thấy một ...] - Steve Chambers


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


Đó là toán tử kết hợp rỗng, và khá giống toán tử ternary (ngay lập tức-nếu). Xem thêm ?? Nhà điều hành - MSDN.

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

mở rộng đến:

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

tiếp tục mở rộng đến:

if(formsAuth != null)
    FormsAuth = formsAuth;
else
    FormsAuth = new FormsAuthenticationWrapper();

Trong tiếng Anh, nó có nghĩa là "Nếu bất cứ điều gì là bên trái không phải là null, sử dụng nó, nếu không thì sử dụng những gì bên phải."

Lưu ý rằng bạn có thể sử dụng bất kỳ số nào trong số này theo thứ tự. Câu lệnh sau sẽ gán đầu tiên không null Answer# đến Answer (nếu tất cả các câu trả lời là null thì Answer là null):

string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;

Nó cũng đáng nói đến trong khi việc mở rộng ở trên là tương đương về khái niệm, kết quả của mỗi biểu thức chỉ được đánh giá một lần. Điều này quan trọng nếu ví dụ một biểu thức là một cuộc gọi phương thức với các hiệu ứng phụ. (Tín dụng cho @Joey để chỉ ra điều này.)


1807
2018-01-15 14:04



không biết rằng ai có thể chuỗi những - Seiti
Có khả năng gây nguy hiểm cho chuỗi này - Coops
@ CodeBlend, nó không nguy hiểm. Nếu bạn đã mở rộng, bạn chỉ có một loạt các câu lệnh if / else lồng nhau. Cú pháp chỉ là lạ vì bạn không quen nhìn thấy nó. - joelmdev
Nó sẽ là một thần gửi nếu nó làm việc cho chuỗi rỗng :) - Zyphrax
@Gusdor ?? là trái, vì vậy a ?? b ?? c ?? d tương đương với ((a ?? b) ?? c ) ?? d. "Các toán tử gán và toán tử bậc ba (? :) là kết hợp đúng. Tất cả các toán tử nhị phân khác đều liên kết trái." Nguồn: msdn.microsoft.com/en-us/library/ms173145.aspx - Mark E. Haase


Chỉ vì chưa có ai nói những lời ma thuật: đó là toán tử kết hợp rỗng. Nó được định nghĩa trong phần 7.12 của Đặc tả ngôn ngữ C # 3.0.

Nó rất tiện dụng, đặc biệt là vì cách nó hoạt động khi nó được sử dụng nhiều lần trong một biểu thức. Biểu thức của biểu mẫu:

a ?? b ?? c ?? d

sẽ cho kết quả biểu đạt a nếu nó không null, nếu không hãy thử b, nếu không thử c, nếu không thử d. Nó ngắn mạch ở mọi điểm.

Ngoài ra, nếu loại d là không có giá trị, kiểu của toàn bộ biểu thức cũng không có giá trị.


232
2018-01-15 14:07



Tôi thích cách bạn đã đơn giản hóa ý nghĩa của nó thành "toán tử kết hợp không". Đó là tất cả những gì tôi cần. - FrankO
Tangential nhưng có liên quan: Nó bây giờ là Swift, nhưng nó rất khác: "Nil Coalescing Operator" developer.apple.com/library/ios/documentation/Swift/Conceptual/… - Dan Rosenstark


Đó là toán tử kết hợp rỗng.

http://msdn.microsoft.com/en-us/library/ms173224.aspx

Có, gần như không thể tìm kiếm trừ khi bạn biết nó được gọi là gì! :-)

EDIT: Và đây là một tính năng thú vị từ một câu hỏi khác. Bạn có thể xích chúng.

Các tính năng ẩn của C #?


64
2018-01-15 14:05



Ít nhất bây giờ, thật dễ dàng để tìm kiếm nó, ngay cả khi bạn không biết tên, tôi chỉ googled "dấu hỏi kép c #" - stivlo


Cảm ơn tất cả mọi người, đây là lời giải thích ngắn gọn nhất tôi tìm thấy trên trang web MSDN:

// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;

21
2018-01-15 14:09



Điều này gợi ý ở một khía cạnh quan trọng của ?? toán tử - nó được giới thiệu để hỗ trợ làm việc với các kiểu nullable. Trong ví dụ của bạn, "x" thuộc loại "int?" (Nullable <int>). - Drew Noakes
Tôi nghĩ đoạn mã nên đọc: int? y = x ?? -1; - vitule
@vitule không, nếu toán hạng thứ hai của toán tử kết hợp null là không nullable, thì kết quả là không nullable (và -1 chỉ là một đồng bằng int, không thể vô hiệu). - Georges Dupéron
Tôi thực sự ước nó đã làm việc như thế này. Tôi muốn làm điều này tất cả các thời gian, nhưng tôi không thể vì biến tôi đang sử dụng không phải là một loại nullable. Làm việc trong coffeescript y = x? -1 - PandaWood


?? là có để cung cấp một giá trị cho một loại nullable khi giá trị là null. Vì vậy, nếu formsAuth là null, nó sẽ trả về FormsAuthenticationWrapper () mới.


16
2018-01-15 14:05





enter image description here

Hai dấu hỏi (??) chỉ ra rằng một toán tử Coalescing của nó.

Toán tử kết hợp trả về giá trị NON-NULL đầu tiên từ một chuỗi. Bạn có thể thấy video youtube này thể hiện toàn bộ điều thực tế.

Nhưng hãy để tôi thêm nhiều hơn vào những gì video nói.

Nếu bạn thấy ý nghĩa tiếng Anh của việc kết hợp nó nói "hợp nhất với nhau". Ví dụ dưới đây là một mã kết hợp đơn giản, chuỗi bốn chuỗi.

Do đó, nếu str1 Là null nó sẽ cố gắng str2, nếu str2 Là null nó sẽ cố gắng str3 và cứ như vậy cho đến khi nó tìm thấy một chuỗi có giá trị không null.

string final = str1 ?? str2 ?? str3 ?? str4;

Nói cách đơn giản Toán tử kết nối trả về giá trị NON-NULL đầu tiên từ một chuỗi.


14
2017-12-16 10:30



Tôi thích lời giải thích này bởi vì nó có một sơ đồ, và sau đó câu cuối cùng giải thích nó theo những thuật ngữ đơn giản như vậy! Nó làm cho nó dễ dàng để hiểu và tăng cường sự tự tin của tôi trong sử dụng. Cảm ơn! - Joshua K


Đó là bàn tay ngắn cho các nhà điều hành ternary.

FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();

Hoặc đối với những người không làm ternary:

if (formsAuth != null)
{
  FormsAuth = formsAuth;
}
else
{
  FormsAuth = new FormsAuthenticationWrapper();
}

9
2018-01-15 14:05



Tôi chỉ sửa chữa chính tả "ternary" nhưng thực sự là toán tử bạn ngụ ý là toán tử điều kiện. Nó xảy ra là toán tử ternary duy nhất trong C #, nhưng tại một số điểm chúng có thể thêm một số khác, tại điểm "ternary" sẽ mơ hồ nhưng "có điều kiện" sẽ không. - Jon Skeet
Đó là viết tắt của một cái gì đó bạn có thể làm với toán tử ternary (điều kiện). Trong hình thức dài của bạn, cả hai bài kiểm tra (!= null) va thu hai formsAuth (sau ?) có thể được thay đổi; trong dạng hợp nhất null, cả hai đều ngầm lấy các giá trị bạn đã cung cấp. - Bob Sammers


Nếu bạn quen thuộc với Ruby, ||= có vẻ giống như của C # ?? với tôi. Đây là một số Ruby:

irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"

Và trong C #:

string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";

9
2018-06-30 17:16



x ||= y desugars đến một cái gì đó như x = x || y, vì thế ?? thực sự giống với đồng bằng hơn || trong Ruby. - qerub
Lưu ý rằng ?? chỉ quan tâm đến null, trong khi || toán tử trong Ruby, như trong hầu hết các ngôn ngữ, là nhiều hơn về null, falsehoặc bất kỳ thứ gì có thể được coi là boolean với giá trị false (ví dụ: bằng một số ngôn ngữ, ""). Đây không phải là một điều tốt hay xấu, chỉ là một sự khác biệt. - Tim S.


Đối với vui chơi giải trí của bạn chỉ (biết bạn là tất cả C # guys ;-).

Tôi nghĩ nó có nguồn gốc từ Smalltalk, nơi nó đã tồn tại trong nhiều năm. Nó được định nghĩa ở đó là:

trong đối tượng:

? anArgument
    ^ self

trong UndefinedObject (còn gọi là lớp của nil):

? anArgument
    ^ anArgument

Có cả hai đánh giá (?) Và không đánh giá các phiên bản (??) của điều này.
Nó thường được tìm thấy trong các phương thức getter cho các biến private-initialized (instance) được khởi tạo, được để lại cho đến khi thực sự cần thiết.


8
2018-01-15 14:31



âm thanh như gói ViewState với thuộc tính trên UserControl. Chỉ khởi tạo trên lần đầu tiên, nếu nó không được thiết lập trước đó. =) - Seiti


Không có gì nguy hiểm về chuyện này. Trong thực tế, nó là đẹp. Bạn có thể thêm giá trị mặc định nếu điều đó là mong muốn, ví dụ:

int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;

8
2018-03-21 21:13



Vì vậy, x1, x2, x3 và x4 có thể là các kiểu không thể gửi được, ví dụ: int? x1 = null; Có đúng không - Kevin Meredith
@KevinMeredith x1 - - x4 PHẢI là các loại nullable: nó không có ý nghĩa để nói, hiệu quả, "kết quả là 0 nếu x4 là một giá trị mà nó không thể có được "(null). "Loại dễ vỡ" ở đây bao gồm cả hai giá trị rỗng giá trị các loại và kiểu tham chiếu, tất nhiên. Nó là một lỗi biên dịch thời gian nếu một hoặc nhiều biến chuỗi (ngoại trừ cái cuối cùng) không phải là nullable. - Bob Sammers