patterncsharpMinor
Evaluate the best common type to fit both of types
Viewed 0 times
typesthebothtypeevaluatefitcommonbest
Problem
Here is an algorithm to evaluate best matching
Evaluate the maximum possible type to fit both of types
Algorithm
Questions
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
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)
FindBaseClassWithmethod
- 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
FindInterfaceWithmethod
Questions
GetInterfaceHierarchyimplementaion
- 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
Mainmethod. Nevertheless, any improvments toTest.Assertare 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:
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.
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.