2012-04-25 25 views
5

tôi đang tạo ra một chuyển đổi chungKhông thể thay đổi loại để nullable trong phương pháp chung

Dưới đây là một số mẫu mã của bộ chuyển đổi chung

bool TryReaderParse<TType>(object data, out TType value) 
{ 
    value = default(TType); 
    Type returnType = typeof(TType); 
    object tmpValue = null; 

    if (returnType == typeof(DateTime)) 
    { 
     tmpValue = StringToDatetime(data.ToString()); 
    } 
    else if (returnType == typeof(DateTime?)) // THIS IF FIRES 
    { 
     tmpValue = StringToNullableDatetime(data.ToString()); 
    } 

    value = (TType)Convert.ChangeType(tmpValue, returnType); // THROWS 
} 

public DateTime? StringToNullableDatetime(string date) 
{ 
    DateTime? datetime = null; 
    if (!string.IsNullOrEmpty(date)) 
    { 
     datetime = DateTime.Parse(date, new CultureInfo(Resources.CurrentCulture)); 
    } 

    return datetime; 
} 

Và đây là cách tôi sử dụng nó:

void foo() 
{ 
    DateTime? date = null; 
    TryReaderParse<DateTime?>("25/12/2012", out date); 
} 

Ngoại lệ được ném cho biết rằng nó không thể chuyển đổi từ DateTime thành Nullable<DateTime>. Kể từ khi, phương thức tạo và trả về một kiểu nullable, làm thế nào việc đúc không thành công?

Cuối cùng, tôi muốn có DateTime không có giá trị, trong ví dụ cụ thể này.

chỉnh sửa Vấn đề là StringToNullableDatetime phương thức trả về một Datetime? và đúc nói rằng không thể chuyển đổi từ Datetime

Kể từ khi phương pháp StringToNullableDatetime trả về một datetime nullable, làm thế nào là nó có thể rằng Convert.ChangeType không thể thấy rằng thông qua đối số là nullable?

Ps. Tôi đã đọc các câu trả lời như this một câu trả lời ngược lại (đúc từ nullable).

Trả lời

18

Ngoại lệ được ném cho biết rằng nó không thể chuyển đổi từ DateTime thành Nullable<DateTime>. Kể từ khi, phương thức tạo và trả về một kiểu nullable, làm thế nào việc đúc không thành công?

Câu hỏi hay. Điều này không thành công vì không có nội dung nào có thể được đóng là không có giá trị. Khi bạn chuyển đổi một số DateTime? thành object, bạn sẽ nhận được tham chiếu null, nếu số DateTime? là không hoặc bạn nhận được giá trị đóng gói giá trị, DateTime. Bạn không bao giờ nhận được một cấu trúc nullable đóng hộp; Không có những điều như vậy.

Vì vậy, bạn kết thúc bằng một trong hai giá trị rỗng hoặc Ngày giờ hợp lệ trong hộp đó. Sau đó, bạn yêu cầu Chuyển đổi để chuyển đổi thành DateTime có thể vô hiệu hóa và Chuyển đổi không biết cách thực hiện điều đó.

Lời khuyên của tôi là bạn từ bỏ dòng tấn công này hoàn toàn; mã này là đường biên giới lạm dụng của generics. Bất kỳ lúc nào bạn thực hiện chuyển đổi trên loại loại chung chung, mã của bạn không còn là chung và có thể bạn đang làm sai. Nếu bạn muốn làm một "thử" phương pháp kiểu cho datetimes sau đó chỉ cần viết rằng:

DateTime? TryReadDateTime(object data) 
{ 
    ... return null if the object cannot be read as a datetime ... 
} 

Viết một phương pháp như vậy cho mỗi loại mà bạn có ý định đọc. Người dùng sẽ có nhiều thay viết:

DateTime? d = TryReadDateTime(data); 
if (d != null) ... 

Thần

DateTime d; 
bool b = TryRead<DateTime>(data, out d); 
if (b) ... 
0

Từ documentation, dòng này sẽ báo lỗi nếu:

giá trị là null và conversiontype là một loại giá trị

Nullable<T> là một cấu trúc và do đó một loại giá trị, do đó bạn không thể sử dụng phương thức này gọi nếu giá trị của bạn là null. Bạn đã xử lý các ngày riêng biệt, vậy tại sao lại sử dụng ChangeType trong những trường hợp đó?

+0

sửa câu hỏi của tôi. Vấn đề của tôi là tôi không thể trả về một datetime Nullable. Dòng 'Convert.ChangeType' không thể thấy rằng đối số đã truyền là nullable – Odys

0

Cách vô hiệu hóa, generics và boxing tương tác là lạ. Bạn có thể được tốt hơn off xác định hai phương pháp:

 
bool TryReaderParse(object data, out TType value); 
bool TryReaderParse(object data, out TType? value) where TType : struct; 

Trong phương pháp thứ hai, mã của bạn chỉ đơn giản là có thể sản xuất một TType và gán nó vào TType? mà không gặp khó khăn.

+2

Trước hết, một phương thức có thể không bị quá tải trên các ràng buộc. Thứ hai, nếu phương thức trả về một giá trị nullable thì tại sao nó cũng cần trả về một bool *? Nếu bạn định làm điều này thì chữ ký bên phải là 'T TryParseClass (dữ liệu đối tượng) trong đó T: class' và' T? TryParseStruct (dữ liệu đối tượng) trong đó T: struct'. Không cần thiết. –

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