patterncsharpMinor
View model with properties that represent years and months
Viewed 0 times
representwithpropertiesviewthatmonthsyearsandmodel
Problem
I have a view model with properties that represent years and months:
I definitely use copy & paste approach here. How can I refactor this code? Maybe somehow passing the numbers as parameters to some helper method?
public IEnumerable Years
{
get
{
return new SelectList(
Enumerable.Range(1900, 112)
.OrderByDescending(year => year)
.Select(year => new SelectListItem
{
Value = year.ToString(CultureInfo.InvariantCulture),
Text = year.ToString(CultureInfo.InvariantCulture)
}
), "Value", "Text");
}
}
public IEnumerable Months
{
get
{
return new SelectList(
Enumerable.Range(1, 12)
.OrderByDescending(month => month)
.Select(month => new SelectListItem
{
Value = month.ToString(CultureInfo.InvariantCulture),
Text = month < 10 ? string.Format("0{0}", month) : month.ToString(CultureInfo.InvariantCulture)
}
), "Value", "Text");
}
}I definitely use copy & paste approach here. How can I refactor this code? Maybe somehow passing the numbers as parameters to some helper method?
Solution
You can use a format string to ensure that there are at least 2 digits in the format without having to check first. The format:
With that, you can create a method with appropriate parameters which can handle both cases:
Note: I suffixed my properties with 2 so I could run them side-by-side and compare results to be sure I didn't miss anything.
Note2: as Jesse suggests, you should ideally cache the results.
{0:00} ensures there are at least 2 digits, but allows for more. It will prefix 0 to any single-digit input.string.Format also has an overload which takes in an IFormatProvider, so my personal preference is just to collapse that into the string.Format call. It also happens to line up nicely :)With that, you can create a method with appropriate parameters which can handle both cases:
public IEnumerable Years2 { get { return BuildList (1900, 112); } }
public IEnumerable Months2 { get { return BuildList (1, 12); } }
public IEnumerable BuildList (int start, int count)
{
return new SelectList (
Enumerable.Range (start, count)
.OrderByDescending (val => val)
.Select (val => new SelectListItem
{
Value = val.ToString (CultureInfo.InvariantCulture),
Text = string.Format (CultureInfo.InvariantCulture, "{0:00}", val)
}
), "Value", "Text");
}Note: I suffixed my properties with 2 so I could run them side-by-side and compare results to be sure I didn't miss anything.
Note2: as Jesse suggests, you should ideally cache the results.
Code Snippets
public IEnumerable<SelectListItem> Years2 { get { return BuildList (1900, 112); } }
public IEnumerable<SelectListItem> Months2 { get { return BuildList (1, 12); } }
public IEnumerable<SelectListItem> BuildList (int start, int count)
{
return new SelectList (
Enumerable.Range (start, count)
.OrderByDescending (val => val)
.Select (val => new SelectListItem
{
Value = val.ToString (CultureInfo.InvariantCulture),
Text = string.Format (CultureInfo.InvariantCulture, "{0:00}", val)
}
), "Value", "Text");
}Context
StackExchange Code Review Q#20832, answer score: 3
Revisions (0)
No revisions yet.