2012-06-08 13 views
21

Một đồng nghiệp cũ làm việc để trích dẫn cha mình về các công cụ, "Bạn phải thông minh hơn nó."Tôi có thực sự muốn trả lại ngày tối thiểu không?

Trong mã bên dưới, Resharper cho tôi biết, "Giá trị được chỉ định không được sử dụng trong bất kỳ đường dẫn thực hiện nào" (trỏ tới dòng đầu tiên). Nếu tôi chấp nhận đề nghị trợ giúp của nó, dt không được chỉ định một giá trị ("hôm nay").

Đây có phải là trường hợp "Tôi phải thông minh hơn" và bỏ qua cảnh báo của họ hay đây là trường hợp công cụ thông minh hơn tôi và tôi chỉ không hiểu nó?

Việc tôi thực hiện là nếu câu lệnh if không thành công, ngày hiện tại được trả về (giá trị mặc định tôi muốn), nhưng nếu tôi chấp nhận "yêu cầu" của Resharper, nó sẽ trả về giá trị mặc định cho ngày giờ, ngày tối thiểu mà tôi giả định là ngày 7/4/1776 hoặc 1/1/0000 hoặc hơn.

DateTime dt = DateTime.Now; 
if (!(DateTime.TryParse(substr, out dt))) { 
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) { 
     if (dtpDlgForm.ShowDialog() == DialogResult.OK) { 
      dt = dtpDlgForm.ReturnVal; 
     } 
    } 
} 
return dt; 
+8

Đây là trường hợp tôi đề nghị bạn sử dụng nhiều lần trả về. Rõ ràng hơn nếu bạn thay dòng cuối cùng bằng 'return DateTime.Now' và dòng ở giữa sử dụng với' return dtpDlgForm.ReturnVal'. –

Trả lời

23

bạn dành Logic cho phép ba giá trị có thể trở lại của DateTime (theo thứ tự ưu tiên):

  1. Giá trị phân tích của substr.
  2. Giá trị được chọn từ hộp thoại.
  3. Ngày và giờ hiện tại.

Bạn có thể thực hiện logic này bằng cách return báo cáo riêng biệt mà được thực hiện khi điều kiện của họ thành công:

DateTime dt; 
if (DateTime.TryParse(substr, out dt)) 
    return dt; 

using (var dtpDlgForm = new ReturnDate(
    "Please select the Date that the file was created:")) 
{ 
    if (dtpDlgForm.ShowDialog() == DialogResult.OK) 
     return dtpDlgForm.ReturnVal; 
} 

return DateTime.Now; 

Sửa: Đối với một lời giải thích về việc tại sao bạn không nên gán giá trị cho một biến mà sẽ được sử dụng làm tham số out, tham khảo Mark Byers’s answer.

+2

Cảm ơn, tất cả các câu trả lời đều tuyệt vời. Tôi đánh dấu phần này là "đúng", bởi vì ngay cả khi ngày đó không bị xáo trộn bởi tên tệp và người dùng sau đó đóng biểu mẫu "hộp thoại" nhắc anh ta/cô ấy cho ngày có kết quả hộp thoại khác với "OK", nó trả về "hôm nay" thay vì 12/7/1941 hoặc bất cứ khi nào: –

+0

Điểm cười nhỏ: dòng tryParse cần một dòng khác –

+0

@ClayShannon: Như Mike Bantegui [đã đề cập ở trên] (http://stackoverflow.com/questions/10952470/would-i-really-want-to-return-the-minimum-date/10952537 # comment14295586_10952470), đây là trường hợp nhiều câu lệnh 'return' có thể thích hợp hơn vì chúng đơn giản hóa luồng của phương thức - bạn có thể chỉ đơn giản giả định rằng phương thức thực thi của phương thức sẽ dừng ngay khi bất kỳ điều kiện xác định' DateTime' thành công nào. chỉ ra lỗi đánh máy 'TryParse', bây giờ f ixed. – Douglas

53

Câu trả lời bạn nhận thấy những gì bạn nên được làm nhưng không giải thích lý do tại sao Resharper than phiền ở nơi đầu tiên. Kể từ khi giải thích này có thể hữu ích cho những người khác tìm thấy câu hỏi của bạn, ở đây nó là:

Bạn nên làm theo lời khuyên Resharper và thay đổi dòng đầu tiên:

DateTime dt; 

này tuyên bố biến dt nhưng không chỉ định bất kỳ giá trị nào cho nó. Không cần gán giá trị ở đây vì nó chắc chắn sẽ được gán trên dòng tiếp theo do out keyword. Từ các tài liệu:

Mặc dù biến chuyển như out tranh luận không cần phải được khởi tạo trước khi được thông qua, được gọi là phương pháp cần thiết để gán một giá trị trước khi phương thức trả về.

Mỏ nhấn mạnh. Gán giá trị DateTime.Now là không cần thiết và gây hiểu nhầm vì giá trị này sẽ không bao giờ được sử dụng.

Đưa tôi về tình hình là nếu câu lệnh if thất bại, ngày hiện tại được trả về

Đó không phải là những gì mã của bạn không. Từ documentation:

kết quả: Khi phương pháp này trở về, chứa giá trị tương đương DateTime với ngày và thời gian chứa đựng trong s, nếu chuyển đổi thành công, hoặc MINVALUE nếu chuyển đổi thất bại.

Với mã bạn được đăng nếu phân tích thất bại thì dt sẽ chứa giá trị DateTime.MinValue và không phải là giá trị DateTime.Now mà bạn được giao.

+0

+1 Giải thích rất tốt. Trong tình huống như thế này, tôi sẽ biết ơn vì có ReSharper ở bên cạnh tôi! Tôi cần phải đi qua tất cả các ứng dụng TryParse của tôi bây giờ .... :( – surfen

20

Đó là vì bạn đang chỉ định giá trị cho dt và sau đó chuyển giá trị đó dưới dạng out param.Nếu một biến được thông qua tại như một hiện param:

  • Nó phải được gán một giá trị bên trong hàm đó trước khi được sử dụng bên trong nó
  • Nó phải được gán một giá trị trước khi hàm trả về

trong trường hợp của bạn, bạn có thể sửa chữa các thông điệp từ nhắn ReSharper bằng cách thay đổi dòng đầu tiên của bạn đến:

DateTime dt; 

mất của tôi trên tình huống là nếu tuyên bố nếu không thành công, thì ngày hiện tại được trả về

Điều này không đúng. Nó sẽ luôn luôn trả DateTime.MinValue, không phụ thuộc vào giá trị của đối tượng DateTime bạn vượt qua trong

Từ MSDN - DateTime.TryParse(string, out DateTime):.

kết quả

Loại: System.DateTime%

Khi phương thức này trả về, [kết quả] chứa giá trị DateTime tương đương với ngày và giờ có trong s, nếu chuyển đổi đã thành công hoặc MinValue nếu chuyển đổi không thành công. Việc chuyển đổi không thành công nếu tham số s là rỗng, là một chuỗi rỗng (""), hoặc không chứa một biểu diễn chuỗi hợp lệ của một ngày và giờ. Thông số này được thông qua chưa được khởi tạo.

(Nhấn mạnh thêm)

8

Thông số out luôn là giá trị được gán cho nó. Nó luôn được đảm bảo rằng hàm được gọi gán một giá trị cho nó trước khi trở về. Do đó nó sẽ ghi đè lên giá trị ban đầu được gán trong mọi trường hợp.

7

Vấn đề ở đây là về việc sử dụng out parameter modifier:

Mặc dù biến chuyển như các đối số ra không cần phải được khởi tạo trước khi được thông qua, được gọi là phương pháp cần thiết để gán một giá trị trước khi trở về phương pháp.

DateTime.TryParse sẽ gán một giá trị mặc định để dt anyways, và nếu nó không thể phân tích substr, kết quả dt sẽ có giá trị của datetime tối thiểu.

3
DateTime.TryParse(substr, out dt); 

có thể trả về false nhưng vẫn sẽ sửa đổi dt. Nó sẽ cố gắng hoàn thành dt với khả năng tốt nhất của nó, khởi tạo một số giá trị tốt nhất có thể. Khi sử dụng out modifier trong C#, bạn đang nói với chương trình để khởi tạo nó, và bạn không nên mong đợi để giữ lại các giá trị mà bạn vượt qua trong.

gì bạn có thể làm là

DateTime dt; 
if (!(DateTime.TryParse(substr, out dt))) { 
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) { 
     if (dtpDlgForm.ShowDialog() == DialogResult.OK) { 
      dt = dtpDlgForm.ReturnVal; 
     } 
     else { 
      dt = DateTime.Now; 
     } 
    } 
} 

return dt; 
+0

Tôi nghĩ rằng mã của bạn sẽ trở lại ngày hôm nay nếu TryParse thành công. Điều đó không đúng, nếu TryParse thành công, giá trị được phân tích cú pháp sẽ được trả về. – comecme

+0

Ôi trời ơi, bạn hoàn toàn đúng. đã thay đổi câu trả lời của tôi để phản ánh điều này. –

3

Mã này sẽ làm cho cảnh báo biến mất. Nhưng tôi nghĩ rằng câu trả lời của Douglas dễ đọc hơn.

DateTime dt; 
if (!(DateTime.TryParse(substr, out dt))) { 
    dt = DateTime.Now; 
    using (var dtpDlgForm = new ReturnDate("Please select the Date that the file was created:")) { 
     if (dtpDlgForm.ShowDialog() == DialogResult.OK) { 
      dt = dtpDlgForm.ReturnVal; 
     } 
    } 
} 
return dt;