How to make a method for two types

I know this is probably a very simple question, but at the moment I have a brain fart. I am trying to create a method that can take one of 2 user types. Basically, the body of this method will be identical for both types, since both of them have the Name property (I use the comparison of the Name property to use when sorting). How can I do it?

My first thought was to simply overload the method with two types as arguments:

int Compare(Type1 first, Type1 second) int Compare (Type2 first, Type2 second) 

but the body of the methods turned out to be identical, so it seems to be waste.

My next thought was to use generics, but that doesn't seem right, because I don't make it general, since it can only be used with two specific types.

Explanation: The "regular" types are not really my custom types. I meant that they are not built-in types. I have no control over what is in these types or the inheritance hierarchy. They both have the Name property.

+4
source share
7 answers

Generic is still an option if two types come from the same base or use the same interface and other classes do not use the base and / or interface.

 int Compare<T>(T first, T second) where T : IHasName 

In addition, having two overloads is the way to go.

Note. If you have .NET 4, you can make it run-time and make the method dynamic.

 int Compare(dynamic first, dynamic second) 

In this case, everything that you throw at it will be compiled, but it will explode at runtime if the Name property is missing.

Personally, if I cannot change the type to use the common interface, then I would go with overloads and get security at compile time.

+7
source

Oddly enough, so far no one has published what seems like an obvious choice: take the name as an argument for comparison. Get the caller to get the name property from the object. If all the method needs to use is a name, then why are you passing the rest of the object?

If you need to ignore the concept of "I can get a name from this thing," then do this:

Example:

 int Compare(string name1, string name2) { ... whatever ... } int Compare<T>(T t1, T t2, Func<T, string> getName) { return Compare(getName(t1), getName(t2)); } 

And now you can say:

 Compare(car1, car2, c=>c.Name); Compare(employee1, employee2, e=>e.Name); 

etc.

+8
source

Ok, I fully understood your question in the first answer. It's better here:)

Overloads are your best bet. Since the result of the comparison depends only on Name , create a method that performs this comparison, then name it:

 private int Compare(string first, string second) { // do comparison } public int Compare(Type1 first, Type1 second) { return Compare(first.Name, second.Name): } public int Compare(Type2 first, Type2 second) { return Compare(first.Name, second.Name); } 

Edit:

Since you have several elements, you can do two things:

 public int Compare(string first1, string second1, X first2, X second2 ... 

But it will be a little ugly. An alternative is to provide a projection for extracting values:

 private int Compare<T>(T first, T second, Func<T,Tuple<string,int,TypeX,TypeY>> projection) { // test for first==null, second==null, etc... var nicerFirst = projection(first); var nicerSecond = projection(second); // compare objects using nicerFirst.Item1, nicerFirst.Item2, etc. } 

Then your comparison looks something like this:

 int Compare(Type1 first, Type1 second) { return Compare(first, second, x => Tuple.Create(x.Name, x.Int, xX, xY)); } 
+4
source

If it can only be used with 2 types, then do 2 overloads.

+1
source

Overloading a method will be a good way to force it to use only two specific types. To avoid code repeating, you can use generics behind the scenes:

 public int Compare(Type1 first, Type1 second) { return Compare<Type1>(first, second); } public int Compare(Type2 first, Type2 second) { return Compare<Type2>(first, second); } private int Compare<T>(T first, T second) { ... } 
+1
source

This may not be the best solution, but this is what comes to my mind: you create a method such as:

 int MainCompare(Type1 first1, Type1 second1, Type2 first2, Type2 second2, bool firsttype){...} 

Then you can use two methods of comparison with one line.

 int compare(Type1 first, Type1 second){ return MainCompare(first, second, null, null, true); } int compare(Type2 first, Type2 second){ return MainCompare(null, null, first, second, false); } 

your MainCompare will simply change the bit depending on what type it uses.

0
source

This is probably a brute force solution, but you can make adapters for two classes and implement them for a common interface:

 public class MyType1 : ICommonInterface, Type1 { // Where you can define 'Somethin' in the common interface public string Something { get { return base.Something; } set { base.Something = value; } } /* ... */ } public class MyType2 : ICommonInterface, Type2 { // If there is no base.Something on Type2, you can re-name it assuming // its intent is the same as Something public string Something { get { return base.SomethingElse; } set { set base.SomethingElse = value; } } } 

Then you can basically implement what @Anthony Pegram (+1):

 int Compare<T> (T first, T second) where T : ICommonInterface { return first.Something.CompareTo(second.Something); } 
0
source

All Articles