11

Tôi đang cố gắng sử dụng toán tử có điều kiện, nhưng tôi bị treo lên trên loại mà nó nghĩ kết quả sẽ là.Gõ kết quả với toán tử có điều kiện trong C#

Dưới đây là một ví dụ mà tôi đã trù định để hiển thị các vấn đề tôi đang gặp:

class Program 
{ 
    public static void OutputDateTime(DateTime? datetime) 
    { 
     Console.WriteLine(datetime); 
    } 

    public static bool IsDateTimeHappy(DateTime datetime) 
    { 
     if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0) 
      return true; 

     return false; 
    } 

    static void Main(string[] args) 
    { 
     DateTime myDateTime = DateTime.Now; 
     OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime); 
     Console.ReadLine();      ^
    }            | 
}             | 
// This line has the compile issue ---------------+ 

Trên dòng nêu trên, tôi nhận được lỗi biên dịch sau:

Loại biểu thức điều kiện không thể được xác định bởi vì không có chuyển đổi tiềm ẩn nào giữa '< null>' và 'System.DateTime'

Tôi nhầm lẫn vì tham số này là một loại không có giá trị (DateTime?). Tại sao nó cần phải chuyển đổi? Nếu nó là null sau đó sử dụng, nếu đó là một thời gian ngày sau đó sử dụng đó.

Tôi đã theo ấn tượng rằng:

condition ? first_expression : second_expression; 

là giống như:

if (condition) 
    first_expression; 
else 
    second_expression; 

Rõ ràng đây không phải là trường hợp. Lý do đằng sau điều này là gì?

(Chú ý:.?. Tôi biết rằng nếu tôi làm cho "myDateTime" một DateTime nullable sau đó nó sẽ làm việc Nhưng tại sao nó cần nó

Như tôi đã nói ở trên đây là một ví dụ contrived Trong ví dụ thật của tôi " myDateTime "là giá trị được ánh xạ dữ liệu không thể thực hiện được.)

+0

thể trùng lặp của [nhiệm vụ điều hành có điều kiện với Nullable loại?] (Http://stackoverflow.com/questions/75746/conditional-operator-assignment-with-nullablevalue-types) – nawfal

+0

thể trùng lặp của [loại Nullable và toán tử ternary: tại sao \ '? 10: null \ 'bị cấm?] (Http://stackoverflow.com/questions/858080/nullable-types-and-the-ternary-operator-why-is-10-null-forbidden) –

Trả lời

22

Trình biên dịch không suy ra loại kết quả của toán tử điều kiện từ việc sử dụng kết quả, nhưng từ các kiểu đối số của nó. Trình biên dịch không thành công khi nó thấy biểu hiện này bởi vì nó không thể suy ra loại kết quả:

IsDateTimeHappy(myDateTime) ? null : myDateTime; 

Kể từ nullDateTime không tương thích, bạn cần phải nói với trình biên dịch những gì các loại nên. Một diễn viên nên thực hiện thủ thuật:

DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime; 
OutputDateTime(x); 

Bây giờ trình biên dịch sẽ không có vấn đề gì.Bạn cũng có thể viết trên trên cùng một dòng nếu bạn thích (nhưng có lẽ tôi sẽ không làm điều này):

OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime); 

Eric Lippert có good answer đó cũng là liên quan ở đây và đi vào chi tiết hơn về cách trình biên dịch xác định loại .

+0

Giải pháp tuyên bố tiết kiệm chi tiết hơn myDateTime là 'DateTime?' để bắt đầu bằng: 'DateTime? myDateTime = DateTime.Now; ' –

1

Chuyển đổi ẩn không được phép bởi câu lệnh trả về. Nếu bạn đã có

if (condition) 
    return first_expression; 
else 
    return second_expression; 

Sau đó, bạn sẽ so sánh táo với táo. Và bạn không có vấn đề gì - như bạn đã nói.

Trong trường hợp của bạn, bạn được phân bổ quá nhiều khoảng trống trên ngăn xếp cho một DateTime - đây là một loại giá trị không thể null. Vì vậy, bạn đang thực hiện một tuyên bố rằng không có ý nghĩa gì với trình biên dịch. Nếu bạn nói, tôi sẽ chuyển cho bạn một số A hoặc B, thì A và số B cần phải giống nhau. Trong trường hợp của bạn, B không bao giờ có thể là A.

2

Lý do là toán tử bậc ba kỳ vọng cả hai toán hạng có cùng loại. Toàn bộ toán tử được tính toán TRƯỚC KHI nó được gán cho một kết quả (trong trường hợp này được truyền vào một hàm), do đó trình biên dịch không thể biết loại kết quả là gì.

IsDateTimeHappy(myDateTime) ? null : myDateTime 

Trong trường hợp trên không có con đường chuyển đổi giữa nullDateTime. Ngay sau khi bạn cast một trong số họ để DateTime?, trình biên dịch có thể chuyển đổi khác một:

IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime 
//OR 
IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime 

Dòng nắm tay mã trên hoạt động vì trình biên dịch có thể chuyển đổi DateTime-DateTime? qua một nhà điều hành chuyển đổi ngầm:

//In Nullable<T> 
public static implicit operator T?(T value); 

Dòng thứ hai hoạt động vì null có thể được gán cho DateTime? vì sau này là loại tham chiếu.

0

gì trình biên dịch được nói là:

If IsDateTimeHappy(myDateTime) is false , then I need to return a value of type DateTime equal to myDateTime . If it is true , then I need to return a value equal to null , but you haven't told me what type it should be!

Đó là lý do tại sao câu trả lời của Mark là giải pháp. Sau khi bạn cung cấp một bộ đúc cho trình biên dịch biết loại giá trị nào sẽ được trả về nếu điều kiện là true, nó có thể kiểm tra xem các giá trị trả về truefalse có thể được chuyển thành (hoặc có) cùng loại hay không.

Chúc mừng Mark! ;-)

0

Thay vì null sử dụng default(DateTime?) và sau đó cả hai mặt của bộ ba sẽ có các loại tương thích.

Các vấn đề liên quan