HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Evaluate the best common type to fit both of types

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
typesthebothtypeevaluatefitcommonbest

Problem

Here is an algorithm to evaluate best matching System.Type for two types in hierarhy. This is one of answers for this StackOverflow question by Ken Kin:


Evaluate the maximum possible type to fit both of types

Algorithm

  • Searching for common base class (either concrete or abstract)



  • FindBaseClassWith method



  • If there is no common base class, search for common implemented interface



  • It's possible for one class to implement multiple interfaces, in this case return first common based interface



  • FindInterfaceWith method



Questions

  • GetInterfaceHierarchy implementaion



  • I'm not sure that this is correct implementation in case of complex class hierarhy with many implemented interfaces



  • Now all tests are passing for selected collection from BCL and my own testing hierarhy



  • Are there any other flaws that I do not pay attention to?



  • I had wrote this sample in LinqPad, that's why all unittests are located at Main method. Nevertheless, any improvments to Test.Assert are ok!



Full source code with unittests is available here

```
// provide common base class or implemented interface
public static Type FindEqualTypeWith(this Type typeLeft, Type typeRight)
{
if(typeLeft == null || typeRight == null) return null;

var commonBaseClass = typeLeft.FindBaseClassWith(typeRight) ?? typeof(object);

return commonBaseClass.Equals(typeof(object))
? typeLeft.FindInterfaceWith(typeRight)
: commonBaseClass;
}

// searching for common base class (either concrete or abstract)
public static Type FindBaseClassWith(this Type typeLeft, Type typeRight)
{
if(typeLeft == null || typeRight == null) return null;

return typeLeft
.GetClassHierarchy()
.Intersect(typeRight.GetClassHierarchy())
.FirstOrDefault(type => !type.IsInterface);
}

// searching for common implemented interface
// it's possible for one class to implement multiple interfaces,
// in this case return first common based in

Solution

Your code does not take in account interface covariance and contravariance issues.

Here is the sample code that demonstrates it:

class ObservableOfString : IObservable { /*...*/ }
class ObservableOfObject : IObservable { /*...*/ }
class ObserverOfObject : IObserver { /*...*/ }
class ObserverOfString : IObserver { /*...*/ }
class Program
{

    static void Main(string[] args)
    {
        IObservable observableIsCovariant = new ObservableOfString();
        IObserver observerIsContravariant = new ObserverOfObject();
        Console.WriteLine(typeof(ObservableOfString).FindEqualTypeWith(typeof(ObservableOfObject)) ?? (object)""); // Would it not be more useful to return IObservable?
        Console.WriteLine(typeof(ObserverOfString).FindEqualTypeWith(typeof(ObserverOfObject)) ?? (object)""); // Would it not be more useful to return IObserver?
        Console.ReadLine();
    }
}


The fundamental issue is, as soon as you want to find the "best common interface", you are going to run in an issue, as "best" and "common" are at best dependent on the context. You should clearly identify which use cases you are going to support, in the context of why that method was needed, and write a specific implementation that solves your need.

Code Snippets

class ObservableOfString : IObservable<string> { /*...*/ }
class ObservableOfObject : IObservable<object> { /*...*/ }
class ObserverOfObject : IObserver<object> { /*...*/ }
class ObserverOfString : IObserver<string> { /*...*/ }
class Program
{

    static void Main(string[] args)
    {
        IObservable<object> observableIsCovariant = new ObservableOfString();
        IObserver<string> observerIsContravariant = new ObserverOfObject();
        Console.WriteLine(typeof(ObservableOfString).FindEqualTypeWith(typeof(ObservableOfObject)) ?? (object)"<NULL>"); // Would it not be more useful to return IObservable<object>?
        Console.WriteLine(typeof(ObserverOfString).FindEqualTypeWith(typeof(ObserverOfObject)) ?? (object)"<NULL>"); // Would it not be more useful to return IObserver<string>?
        Console.ReadLine();
    }
}

Context

StackExchange Code Review Q#20369, answer score: 5

Revisions (0)

No revisions yet.