Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refactor these generic methods?

UPDATE: I should have mentioned in the original post that I want to learn more about generics here. I am aware that this can be done by modifying the base class or creating an interface that both document classes implement. But for the sake of this exercise I'm only really interested in solutions that do not require any modification to the document classes or their base class. I thought that the fact that the question involves extension methods would have implied this.

I have written two nearly identical generic extension methods and am trying to figure out how I might refactor them into a single method. They differ only in that one operates on List and the other on List, and the properties I'm interested in are AssetID for AssetDocument and PersonID for PersonDocument. Although AssetDocument and PersonDocument have the same base class the properties are defined in each class so I don't think that helps. I have tried

public static string ToCSVList<T>(this T list) where T : List<PersonDocument>, List<AssetDocument>

thinking I might then be able to test the type and act accordingly but this results in the syntax error

Type parameter 'T' inherits conflicting constraints

These are the methods that I would like to refactor into a single method but perhaps I am simply going overboard and they would best be left as they are. I'd like to hear what you think.

public static string ToCSVList<T>(this T list) where T : List<AssetDocument>
{
  var sb = new StringBuilder(list.Count * 36 + list.Count);
  string delimiter = String.Empty;

  foreach (var document in list)
  {
    sb.Append(delimiter + document.AssetID.ToString());
    delimiter = ",";
  }

  return sb.ToString();
}

public static string ToCSVList<T>(this T list) where T : List<PersonDocument>
{
  var sb = new StringBuilder(list.Count * 36 + list.Count);
  string delimiter = String.Empty;

  foreach (var document in list)
  {
    sb.Append(delimiter + document.PersonID.ToString());
    delimiter = ",";
  }

  return sb.ToString();
}
like image 263
Steve Crane Avatar asked Mar 12 '10 10:03

Steve Crane


People also ask

What are generic methods?

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

How can generic method be overloaded?

A generic method may be overloaded like any other method. A class can provide two or more generic methods that specify the same method name but different method parameters. For example, generic method printArray of Fig.

How to use Generics in intellij?

If you want to apply generics to a single code fragment, select one in the editor. On the main menu, or on the context menu, select Refactor | Convert Raw Types to Generics. In the dialog that opens, define the refactoring options. Preview and apply changes.


2 Answers

Your implementation is basically reimplementing string.Join method, so you might try to make it simpler and more generic with some LINQ:

public static string ToCSVList<T>(this IEnumerable<T> collection)
{ return string.Join(",", collection.Select(x => x.ToString()).ToArray()); }

public static string ToCSVList(this IEnumerable<AssetDocument> assets)
{ return assets.Select(a => a.AssetID).ToCSVList(); }

public static string ToCSVList(this IEnumerable<PersonDocument> persons)
{ return persons.Select(p => p.PersonID).ToCSVList(); }
like image 74
Bojan Resnik Avatar answered Oct 04 '22 20:10

Bojan Resnik


I think the way would be to let PersonDocument and AssetDocument inherit from a Document class, which would have an Id property, that stores your current PersonId or AssetId respectivly.

like image 44
Jens Avatar answered Oct 04 '22 20:10

Jens