• 0

Partial Type checking before using dynamic? Good or Bad?


Question

I have this (as well as Subtract, Divide, etc. I chose not to go w/ static operators),

public interface Add<T, G>
{
T Add(G b);
}

T, G are guaranteed to be data classes (not yet in code)

All data classes implement SType interface and SType is what gets passed around.

 

So the SType interface does not contain any information about whether or not a data class implements Add<T,G> (and data classes can implement multiple Add<T,G> interfaces).

public interface SType : SEquatable
{
void Print(int flag, TextWriter file);
}

So the overloaded (nothing known, output known, input known, both known) function I am trying to write takes two data classes and either adds them and returns a data class OR throws a custom exception.

 

Now when T and G are known,

I just use the as keyword to cast the SType interface to Add<T,G> interface and if it returns null, I throw an exception.

var addable = _this as Add<X, G>;

Now what if I don't know T or G (don't know what goes in and goes out)? Or just know T? Or just know G?

 

The easy solution is to use dynamic in a try catch. Like,

((dynamic)_this).Add(_other)

Questions,

1. If generic arguments are not known (or partially known), in terms of performance, is better to check that there is ANY implementation of Add interface before using dynamic to attempt to invoke it?

Something like (not tested),

bool possibleMatch = 
this.Data().GetType().GetInterfaces()
.Where(i => i.IsGenericType)
.Where(i => i.GetGenericTypeDefinition() == typeof(Add<,>))
.SelectMany(i => i.GetGenericArguments())
.Any(type => type == _data.GetType());
Link to comment
Share on other sites

3 answers to this question

Recommended Posts

  • 0

There is no point in defining an interface if you're going to end up invoking the method by dynamic dispatching. Interfaces provide compile-time contracts; dynamic dispatching bypasses that completly. It seems to me like you're trying to work around a design problem with your class hierarchy rather than to address it. If you need to bypass your own class design that probably means your class design needs to be revised.

 

Your question would be easy to answer with a simple benchmark, but rather than concern yourself with the performance issues, I think you should attempt to modify your design so you don't need to resolve this type information at run-time.

Link to comment
Share on other sites

  • 0

There is no point in defining an interface if you're going to end up invoking the method by dynamic dispatching. Interfaces provide compile-time contracts; dynamic dispatching bypasses that completly. It seems to me like you're trying to work around a design problem with your class hierarchy rather than to address it. If you need to bypass your own class design that probably means your class design needs to be revised.

 

Your question would be easy to answer with a simple benchmark, but rather than concern yourself with the performance issues, I think you should attempt to modify your design so you don't need to resolve this type information at run-time.

I think I need ideas... :(

 

Issue is I have no information about what two data types a user will try to run an operator on.

The only other solution I see is having all interfaces implement a single function which takes in a data type interface and gives back a data type interface.

 

Something like this,

public interface SType : SEquatable 
{
void Print(int flag, TextWriter file); 
SType Add(SType b);
// and others
}

 

I will have to explicitly check what concrete class SType is. If it is A do this, if it is B then this, if it is C do this, .., else throw (because C# doesn't support switch on Type). Feels nasty.

Also I would not know what is returned. I can do that - My first choice was to have all classes to have same operators but then I realized that in C# you cannot force implementing classes to have operators.

Then there are things like,

public static SExpression<T> Generate<T>(T Data = default(T))
where T : SType, new()
{
return new SExpression<T>(Data);
}

I cannot pass an instantiation of SType to this method, without casting SType to a specific class or using dynamic. There doesn't seem to be a parameter less constructor constraint for interfaces.

Link to comment
Share on other sites

  • 0
I will have to explicitly check what concrete class SType is. If it is A do this, if it is B then this, if it is C do this, .., else throw (because C# doesn't support switch on Type). Feels nasty.

This is the very thing virtual methods solve: choosing a behavior based on the concrete run-time type.

 

Also I would not know what is returned.

Why do you need to know what is returned? If you need to do something polymorphic with the result, again, that's what virtual methods solve.

 

I don't understand why you're even using generics. The description of your problem sounds like something you solve with good old polymorphism.

 

As for your factory method issue, that could be solved with using an abstract class rather than an interface as the common subtype; then again it's not clear why you need that method.

Link to comment
Share on other sites

This topic is now closed to further replies.