2017-11-11 25 views
21

Vì một số lý do, M1() gây ra lỗi trình biên dịch, trong khi M2(), thực hiện tương tự, không gây ra lỗi. Bất kỳ ý tưởng tại sao?C# 7 Lỗi trình biên dịch - So khớp mẫu

Sử dụng false == phải giống như sử dụng toán tử không, !.

Sử dụng biến cục bộ unassigned 'i'

class Program { 
    static void Main(string[] args) { 
     int x = 8; 

     M1(x); 
     M2(x); 
    } // Main() 

    public static void M1(Object obj) { 
     if (false == (obj is int i)) // Causes ERROR on WriteLine 
      return; 

     System.Console.WriteLine(i); // Use of unassigned local variable 'i' 
    } 

    public static void M2(Object obj) { 
     if (!(obj is int i)) // OKAY 
      return; 

     System.Console.WriteLine(i); 
    } 
} // class Program 
+0

có vẻ như tôi nằm ngoài phạm vi đối với trường hợp cạnh của M1? –

+0

@ Aominè Tôi có thể thấy nó trong VS 15.2 (VS-> help-> about) ... Bạn sử dụng cái gì? –

+2

@PatrickArtner Rõ ràng là không. Nếu 'i' nằm ngoài phạm vi, lỗi sẽ không nói" biến cục bộ chưa được gán ". Bạn chỉ có thể nhận được lỗi đó cho các biến nằm trong phạm vi. – hvd

Trả lời

0

find tốt, đây là những gì tôi nghĩ. lưu ý rằng đây chắc chắn là thứ có thể khắc phục được, nhưng tôi đang cố gắng tìm ra lý do cho nó. lưu ý rằng đây không phải là câu trả lời chính xác. chỉ nói!

không chỉ là false == gây ra sự cố này, mà còn == true khiến i trở nên không thể sử dụng được ở một trong hai nhánh, vì vậy tôi đã tiếp tục và viết điều này.

var x = obj is int i; 
if(x) Console.WriteLine(i); 

bạn gặp lỗi tương tự. như bạn có thể thấy nếu x là đúng thì i phải được khởi chạy, phải không? trừ khi bạn bắt đầu muck với giá trị x! ở đây x không phải là hằng số do đó chúng tôi không thể đảm bảo rằng x luôn luôn đúng trước khi thực hiện nếu tuyên bố.

cách trình biên dịch có thể tính giá trị và biểu thức không đổi tại thời gian biên dịch. Tôi không chắc chắn những gì đang xảy ra ở đây nhưng những gì tôi nghĩ là

if((obj is int i) == false)

đây == hành đặt một khoảng cách giữa kết quả của mô hình kết hợp và đánh giá các câu lệnh if, vì thế mà lỗi. Tôi không biết tại sao nhà điều hành ! hoạt động tốt, có lẽ họ đã tối ưu hóa phần đó nhưng quên tối ưu hóa điều này? ;)

Tôi nghĩ rằng điều này liên quan đến giai đoạn phân tích ngữ nghĩa của trình biên dịch, công việc của nó là xác thực ý nghĩa của mã của bạn và xác định cách thực thi của nó, nếu có điều gì sai, nếu có khả năng hành vi không xác định hoặc vô nghĩa, nó không thành công và bạn nhận được lỗi thời gian biên dịch. đọc thêm về Phases of Compiler Design

14

Vấn đề ở đây là cách trình biên dịch xử lý "chắc chắn được gán khi đúng". ! đảo ngược; == false thì không. Vì vậy, đối mã:

if (!(obj is int i)) 
     return; 

System.Console.WriteLine(i); 

Trình biên dịch có thể suy ra rằng nếu obj is int i là false, ! đảo ngược đó, do đó return sẽ xảy ra nếu nó không phải là một int. Do đó, i có thể được phép "rò rỉ" vào mã tiếp theo một cách an toàn.

Tuy nhiên, các quy tắc tương tự không áp dụng cho == false. Trong khi ngữ nghĩa giống hệt với một người đọc mã nguồn, trình biên dịch xử lý !== false là những thứ rất khác nhau. Vì vậy, đối với:

if (false == (obj is int i)) 

baulks trình biên dịch và xem nó không thể biết trạng thái gán i, do đó là lỗi.

Để thảo luận về điều này, vui lòng xem Incorrect "Use of unassigned local variable" for (x is T y) == false.

Các đạo đức của câu chuyện: tránh so với false và sử dụng ! khi sử dụng C# mẫu.

EDIT

Cần lưu ý rằng == false không phải là một trường hợp đặc biệt ở đây. Bất kỳ việc sử dụng nào của == sẽ loại bỏ khả năng của trình biên dịch để xác định "chắc chắn được gán khi đúng". Ví dụ, đoạn mã sau biên dịch:

object x = 1; 
if (!(x is bool y)) 
    return 0; 

var z = y; 

Nhưng thêm một == true và nó không còn thực hiện:

object x = 1; 
if (!(x is bool y == true)) 
    return 0; 

var z = y; // error: use of an unassigned variable 

EDIT2

Ngẫu nhiên, cho bất cứ ai sử dụng if (expression == false) vì họ thấy if (!expression) khó đọc, bạn có thể muốn biết rằng the syntax, if !(expression) is being considered for C# 8.

+0

'!' Vẫn là toán tử, nó đã thực hiện như '=='. tại sao trình biên dịch không thể tối ưu hóa '== sai'? lưu ý rằng phần '== false' là hằng số. nó có thể được tối ưu hóa, nhưng tiếc là trình biên dịch phát ra lỗi trước khi thực hiện điều đó. –

+2

@ M.kazemAkhgary, nó khá có thể nó có thể được cải thiện theo cách đó. Nếu bạn cảm thấy bị thông cảm về nó, thì hãy [nêu vấn đề về repo ngôn ngữ C#] (https://github.com/dotnet/csharplang/issues) để yêu cầu. –

+0

@DavidArno đã có vấn đề ở đó: https://github.com/dotnet/csharplang/issues/801 – Evk

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