Làm cách nào để sử dụng DateTime.TryParse với một <DateTime> Nullable?


115

Tôi muốn sử dụng phương thức DateTime.TryParse để lấy giá trị ngày giờ của một chuỗi thành Nullable. Nhưng khi tôi thử điều này:

DateTime? d;
bool success = DateTime.TryParse("some date text", out (DateTime)d);

trình biên dịch nói với tôi

đối số 'out' không được phân loại là một biến

Không chắc tôi cần làm gì ở đây. Tôi cũng đã thử:

out (DateTime)d.Value 

và điều đó cũng không hoạt động. Có ý kiến ​​gì không?

Câu trả lời:


123
DateTime? d=null;
DateTime d2;
bool success = DateTime.TryParse("some date text", out d2);
if (success) d=d2;

(Có thể có nhiều giải pháp thanh lịch hơn, nhưng tại sao bạn không đơn giản làm điều gì đó như trên?)


3
Bạn nói đúng, tôi đang tìm kiếm thêm một lớp lót để hoàn thành công việc, nhưng tôi cho rằng điều này sẽ làm được. Không thích tạo biến tạm thời đó, cảm thấy lộn xộn. : - / Có vẻ như kịch bản này nên được hỗ trợ tốt hơn.
Brian Sullivan

1
xem gợi ý của Binary Worrier để psuedo-inline đó thành một phương thức mở rộng.
David Alpert

4
Tại sao bạn truyền DateTime thành DateTime? Bạn không cần phải lùi lại d2 trước khi chuyển nó vào TryParse.
Aaron Powell

@Slace - Tôi đã cập nhật câu trả lời để kết hợp đề xuất của bạn.
Drew Noakes

@Jason Kealey Tôi hy vọng điều này đã được giới thiệu trong VS2012, nếu không, tôi sẽ phải tiếp tục sử dụng đoạn mã tốt này.
Pimenta

161

Như Jason nói, bạn có thể tạo một biến đúng loại và chuyển nó. Bạn có thể muốn đóng gói nó trong phương pháp của riêng bạn:

public static DateTime? TryParse(string text)
{
    DateTime date;
    if (DateTime.TryParse(text, out date))
    {
        return date;
    }
    else
    {
        return null;
    }
}

... hoặc nếu bạn thích toán tử điều kiện:

public static DateTime? TryParse(string text)
{
    DateTime date;
    return DateTime.TryParse(text, out date) ? date : (DateTime?) null;
}

Hoặc trong C # 7:

public static DateTime? TryParse(string text) =>
    DateTime.TryParse(text, out var date) ? date : (DateTime?) null;

5
Tôi có lẽ không nên tranh luận với The Skeet, nhưng ... bạn nên gọi phương thức của mình là Parse, vì tôi mong đợi một phương thức gọi là TryParse tuân theo quy ước TryParse và trả về một boolean. ;-)
Myster

@Myster: Trong cả hai trường hợp, nó đều không tuân theo quy ước chính xác hiện có - những người từng chỉ Parsemong đợi nó quay trở lại DateTimevà ném một ngoại lệ khi thất bại, phải không? Nhưng có, bạn có thể làm bất cứ điều gì bạn muốn ... và trong Noda Time, tôi đã đặt tên cho các phương pháp có liên quan Parse.
Jon Skeet

1
Các elsetừ khóa là không cần thiết (trong ví dụ đầu tiên của bạn) kể từ cuối điểm của ifkhối không bao giờ có thể đạt được.
Jeppe Stig Nielsen

1
@JeppeStigNielsen: Đúng, nó không cần thiết - nhưng nó có thể thích hợp hơn về mặt phong cách cho sự đối xứng. Nó chỉ là một sở thích cá nhân (và tôi là không phù hợp, hoặc là ...)
Jon Skeet

3
@Kiquenet: sử dụng else làm rõ ràng hơn rằng một hoặc đường dẫn khác sẽ được thực hiện và cả hai đều quay trở lại. Tôi chống lại mã lồng nhau ồ ạt, nhưng trong trường hợp này, nó thực sự không phải là vấn đề IMO.
Jon Skeet

20

Dưới đây là một phiên bản ngắn gọn về những gì Jason đã đề xuất:

DateTime? d; DateTime dt;
d = DateTime.TryParse(DateTime.Now.ToString(), out dt)? dt : (DateTime?)null;

18

Bạn không thể vì Nullable<DateTime>là một loại khác nhau DateTime. Bạn cần viết hàm của riêng mình để làm điều đó,

public bool TryParse(string text, out Nullable<DateTime> nDate)
{
    DateTime date;
    bool isParsed = DateTime.TryParse(text, out date);
    if (isParsed)
        nDate = new Nullable<DateTime>(date);
    else
        nDate = new Nullable<DateTime>();
    return isParsed;
}

Hi vọng điêu nay co ich :)

CHỈNH SỬA: Đã xóa phương thức tiện ích mở rộng (rõ ràng) đã được kiểm tra không thích hợp, bởi vì (như Được chỉ ra bởi một số phương pháp mở rộng không hợp lệ) cố gắng thay đổi thông số "this" sẽ không hoạt động với Loại giá trị.

PS The Bad Hoor được đề cập là một người bạn cũ :)


Ya không muốn bắt đầu ngày tháng [vì bạn đang sử dụng nó như một thông số bên ngoài] OK, tôi sẽ ngừng kén chọn!
Ruben Bartelink

Tôi không có trình biên dịch, nhưng vì DateTime là một loại giá trị, nên phương thức mở rộng def có biên dịch không?
Ruben Bartelink

Kết quả sẽ không quay lại trừ khi bạn xác định được - [TestFixture] public class WhenExfining {[Test] public void TryParseShouldWork () {DateTime? x = null; var res = Externders.TryParse (x, "1/1/1990"); Assert.IsTrue (res)
Ruben Bartelink

; Assert.That (x! = Null); }} Thất bại trên Assert.That, tức là, kết quả doesnt có được sửa đổi như DateTime là một loại giá trị (mà luôn luôn là một câu hỏi thoải mái cỏ dại ra trên màn hình điện thoại: D)
Ruben Bartelink

(obv cái đầu tiên (không phải tiện ích mở rộng) sẽ hoạt động, nhưng nó phải bị out, không phải ref - và bạn nên vô hiệu hóa kết quả nếu nó không phù hợp với các API TryXXX nói chung - Khá chắc chắn FDG đã đề cập đến điều đó. Người đàn ông, tôi tôi kén chọn!
Ruben Bartelink

4

Điều gì về tạo một phương thức mở rộng?

public static class NullableExtensions
{
    public static bool TryParse(this DateTime? dateTime, string dateString, out DateTime? result)
    {
        DateTime tempDate;
        if(! DateTime.TryParse(dateString,out tempDate))
        {
            result = null;
            return false;
        }

        result = tempDate;
        return true;

    }
}

2
Tham số đầu tiên đó là gì dateTime, để làm gì? Nó không bao giờ được sử dụng.
Mike Zboray 21/10/12

1
@mikez - đó là cách hoạt động của các phương thức mở rộng, nó được trình biên dịch sử dụng để biết rằng nó phải là một phương thức mở rộng.
Erik Funkenbusch

3
@MystereMan Tôi biết phương thức mở rộng là gì. Một chữ ký thích hợp hơn cho một phương thức mở rộng sẽ là DateTime? TryParse(this string dateString). Việc thực hiện này chỉ là kỳ lạ.
Mike Zboray

3
@mikez - vậy tại sao bạn lại hỏi nó dùng để làm gì? Tại sao lại gây ô nhiễm không gian tên chuỗi khi bạn chỉ cần nó cho datetime? Mục đích là cung cấp một tương tự cho DateTime.TryParse tức là DateTime? .TryParse
Erik Funkenbusch

1
@ErikFunkenbusch Phương thức mở rộng này sẽ không cho phép gọi cú pháp như (DateTime?).TryParse( ... )hoặc Nullable<DateTime>.TryParse( ... ). Vì vậy, mike z nói đúng, đây là một chữ ký ngớ ngẩn cho phương pháp.
Jeppe Stig Nielsen,

1

Tôi không hiểu tại sao Microsoft không xử lý điều này. Một phương pháp tiện ích nhỏ thông minh để giải quyết vấn đề này (Tôi đã gặp vấn đề với int, nhưng việc thay thế int bằng DateTime sẽ có hiệu quả tương tự, có thể là .....

    public static bool NullableValueTryParse(string text, out int? nInt)
    {
        int value;
        if (int.TryParse(text, out value))
        {
            nInt = value;
            return true;
        }
        else
        {
            nInt = null;
            return false;
        }
    }

1

Đây là một lớp lót mà bạn đang tìm kiếm:

DateTime? d = DateTime.TryParse("some date text", out DateTime dt) ? dt : null;

Nếu bạn muốn biến nó thành một phương pháp mở rộng giả TryParse thích hợp, bạn có thể làm như sau:

public static bool TryParse(string text, out DateTime? dt)
{
    if (DateTime.TryParse(text, out DateTime date))
    {
        dt = date;
        return true;
    }
    else
    {
        dt = null;
        return false;
    }
}

@robnick Điều đó khác gì so với những gì tôi đã nói?
cpcolella

1
Bỏ qua nhận xét trước đó của tôi (Tôi đã ủng hộ giải pháp của bạn!), Đối với C # mới nhất, tôi cần truyền null: DateTime? d = DateTime.TryParse (blah, hết DateTime dt)? dt: (DateTime?) null;
robnick

1

Đây là một giải pháp dòng đơn:

DateTime? d = DateTime.TryParse("text", out DateTime parseDate) ? parseDate : (DateTime?)null;

-3

Ngoài ra, nếu bạn không quan tâm đến ngoại lệ có thể được nêu ra, bạn có thể thay đổi TryParse cho Parse:

DateTime? d = DateTime.Parse("some valid text");

Mặc dù cũng sẽ không có boolean biểu thị thành công, nhưng nó có thể thực tế trong một số trường hợp mà bạn biết rằng văn bản đầu vào sẽ luôn hợp lệ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.