2009-12-04 11 views
47

Một vài trong số đối tượng tên miền của tôi chứa phạm vi ngày như một cặp bắt đầu và ngày kết thúc các thuộc tính:Tôi có nên tạo đối tượng DateRange không?

public class Period { 
    public DateTime EffectiveDate { get; set; } 
    public DateTime ThroughDate { get; set; } 
} 

public class Timeline { 
    public DateTime StartDate { get; set; } 
    public DateTime EndDate { get; set; } 
} 

Và tôi thấy mình với rất nhiều về điều này:

abstract public int Foo(DateTime startDate, DateTime endDate); 
abstract public decimal Bar(DateTime startDate, DateTime endDate); 
abstract public ICollection<C5.Rec<DateTime, DateTime>> FooBar(DateTime startDate, DateTime endDate); 

Người cuối cùng làm tôi tự hỏi ... Tôi có nên triển khai lớp DateRange không? Tôi không biết một trong BCL.

Theo kinh nghiệm của tôi, việc phân cấp đối tượng thường làm phức tạp hơn mọi thứ. Các đối tượng này được gửi đến các báo cáo RDLC được hiển thị bởi điều khiển ReportViewer, nhưng đó là thứ cấp. Tôi sẽ uốn cong khung nhìn sang mô hình chứ không phải ngược lại. Chúng tôi không gắn liền với tên thuộc tính, tuy nhiên, và sẽ sẵn sàng thỏa hiệp với cái gì đó như: xác nhận

public class DateRange { 
    public DateTime StartDate { get; set; } 
    public DateTime EndDate { get; set; } 
} 

Period p = new Period(); 
DateTime t = p.EffectiveDateRange.StartDate; 

Một lợi ích của một lớp datarange sẽ được tập trung trong những ngày kết thúc đến sau ngày bắt đầu, và nó sẽ đơn giản hóa chữ ký của phương thức của tôi:

abstract public int Foo(DateRange dateRange); 
abstract public decimal Bar(DateRange dateRange); 
abstract public ICollection<DateRange> FooBar(DateRange dateRange); 

Tôi không chắc rằng lớp DateRange sẽ không khiến tôi gặp rắc rối hơn giá trị của nó. Ý kiến?

Câu hỏi phụ: Tôi có bỏ lỡ một lớp tuple có mục đích chung chung trong BCL ở đâu đó không? Tôi biết có một số người rất cụ thể nổi xung quanh trong không gian tên khác nhau. Ô nhiễm chữ ký tên miền công cộng của tôi với các loại C5 cảm thấy rất, rất bẩn.

+0

Tôi chắc chắn nghĩ rằng lớp DateRange có thể giúp ích. Tôi bắt đầu viết nền tảng cho một thời gian trở lại: http://www.adamjamesnaylor.com/2012/11/04/C-DateRange-Class.aspx –

+0

@AdamNaylor: Các liên kết của bạn dường như ... – testing

Trả lời

33

Không, bạn không bỏ lỡ một lớp học có mục đích chung.

Tôi có loại Range trong MiscUtil mà bạn có thể quan tâm - và nó chắc chắn làm cho thao tác DateTime đơn giản. Đề cập đến câu trả lời của Marc, tôi không thể nhớ đây có phải là cấu trúc hay một lớp hay không - bạn có thể thay đổi nó trong khóa học.

Thật tuyệt vời và dễ dàng để vượt qua, do các tướng quân của Generics Marc (giả sử bạn đang sử dụng .NET 3.5, ít nhất - nó khả thi với 2.0 nhưng không được hỗ trợ tại thời điểm này);

Range<DateTime> range = 19.June(1976).To(DateTime.Today); 

foreach (DateTime date in range.Step(1.Days()) 
{ 
    // I was alive in this day 
} 

(Đó cũng đang sử dụng một loạt các phương pháp khuyến nông -. Hữu ích hơn cho thử nghiệm hơn sản xuất)

Để giải quyết những điểm khác trong câu trả lời của Marc, Noda Time chắc chắn sẽ có thể để diễn tả khái niệm về một ngày thích hợp hơn API .NET, nhưng chúng tôi không có bất kỳ thứ gì giống như một phạm vi vào lúc này ... Đó là một ý tưởng hay - mặc dù tôi đã thêm một feature request.

+0

Xin lỗi nếu tôi nói sai về thời gian Noda - có vẻ như nó rất phù hợp với những người quan tâm đến thời gian. –

+0

Không, rất tốt - nếu bạn không đề cập đến nó, tôi không chắc liệu tôi có nghĩ đến việc thêm yêu cầu tính năng vào dự án hay không :) Tôi nghĩ rằng đó là một yêu cầu khá phổ biến - bit khéo léo sẽ làm việc những gì cần thiết để phù hợp với các tinh chỉnh khác nhau mà mọi người sẽ muốn! –

+9

Cú pháp thú vị. –

5

Nếu bạn làm rất nhiều công việc với ngày tháng, có - một phạm vi có thể hữu ích. Đây thực sự là một trong những trường hợp rất hiếm khi bạn nên có thể viết nó là struct (không thay đổi). Tuy nhiên, lưu ý rằng "Thời gian Noda" có thể sẽ cung cấp cho bạn tất cả những điều này và hơn thế nữa (khi nó hoàn thành). Tôi đã lập lịch trình phần mềm trước đó; Tôi đã có một vài cấu trúc như vậy (cho các công việc hơi khác nhau).

Lưu ý, không có cấu trúc BCL tiện dụng cho việc này.

Ngoài ra - hãy nghĩ đến tất cả các phương pháp tuyệt vời (và có thể là toán tử) mà bạn có thể tập trung khi bạn có phạm vi; "chứa" (của một datetime? của một phạm vi khác? bao gồm/loại trừ giới hạn?), "intersects", offset-by (một khoảng thời gian), vv A xác định trường hợp để có một loại để xử lý nó. Lưu ý rằng ở mức ORM, điều này sẽ dễ dàng hơn nếu ORM của bạn hỗ trợ các giá trị tổng hợp - tôi tin rằng NHibernate có, và có thể là EF 4.0.

+0

Oh yes , Noda. Chờ đợi cho nó .... –

+0

Cho rằng đây là một tái cấu trúc để xử lý ngày tốt hơn và phạm vi thao tác, tôi cho rằng nó có ý nghĩa để cung cấp cho nó một lớp học. Tôi chỉ ước mình đã sử dụng NHibernate trong dự án này. Tất cả những giờ đó đã mất đi một văn bản khá hay nếu tôi nói như vậy, nhưng nhạt nhẽo so với DAL. Dự án tiếp theo, mặc dù. Tôi đang chơi với nó ngay bây giờ để có được hang của nó. –

0

Tôi không biết bất kỳ lớp .NET gốc nào của bản chất DateRange. Gần nhất có lẽ là kết hợp DateTime + TimeSpan hoặc DateTime/DateTime.

Tôi nghĩ những gì bạn muốn là khá âm thanh.

0

Như Mark và Jon đã đề cập, tôi sẽ tạo điều này dưới dạng loại giá trị, không thay đổi. Tôi sẽ lựa chọn để thực hiện nó như là một cấu trúc, và thực hiện các giao diện IEquatable và IComparable.

Khi sử dụng ORM như NHibernate, bạn sẽ có thể lưu trữ loại giá trị bên trong bảng đại diện cho một thực thể.

+0

Vì vậy, nó không phải là khó khăn để có một đối tượng phụ DateRange nhưng giữ cấu trúc bảng phẳng với cột ngày bắt đầu và kết thúc bằng cách sử dụng NHibernate (lưu loát)? Tôi sẽ không nghĩ như vậy, nhưng nó là tốt để biết trước thời hạn. –

+0

Bạn có thể triển khai DateRange của mình dưới dạng đối tượng giá trị và sử dụng nó trong NHibernate làm 'thành phần'. Sau đó, bạn thực sự có thể giữ cấu trúc bảng phẳng với cột ngày bắt đầu & kết thúc. –

5

Trong .NET 4.0 hoặc cao hơn, Tuple <> loại đã được thêm để xử lý nhiều giá trị.

Với loại bộ, bạn có thể xác định kết hợp các giá trị của riêng bạn khi đang di chuyển. Vấn đề của bạn rất phổ biến và tương tự như khi một hàm muốn trả về nhiều giá trị. Trước đây, bạn phải sử dụng các biến hoặc tạo một lớp mới chỉ cho phản hồi của hàm.

Tuple<DateTime, DateTime> dateRange = 
    new Tuple<DateTime, DateTime>(DateTime.Today, DateTime.Now); 

Dù bạn đi theo con đường nào, tôi nghĩ bạn chắc chắn đang sử dụng đúng phương pháp. Bạn đang đưa ra ý nghĩa thực sự cho những gì hai ngày kết hợp với nhau. Đó là mã tự viết và theo cách lớn nhất, ngay trong cấu trúc của mã.