Suppose you are writing a class for a generic vector and you want to naively implement a method to add two vectors:
public class Vec<T>
{
public T x { get; set; }
public T y { get; set; }
public Vec() { }
public Vec( T x, T y ) { this.x = x; this.y = y; }
public static Vec<T> Add( Vec<T> v1, Vec<T> v2 )
{
return new Vec<T>( v1.x + v2.x, v1.y + v2.y );
}
}
This won’t work. The compiler is unable to interpret the “+” for type T so v1.x + v2.x cannot be compiled.
One of possible approaches could be to restrict possible Ts with a type constraint so that “+” can be replaced with a method of an interface implemented by T. Such approach, however, does not take you anywhere since you cannot impose an interface on an existing type and thus, Vec<int> or Vec<double> would still fail to compile.
Another common approach is to define an auxiliary interface:
public interface IAdder<T>
{
T Add( T t1, T t2 );
}
so that Vec::Add can be now implemented as:
public static Vec<T> Add( Vec<T> v1, Vec<T> v2, IAdder<T> Adder )
{
return new Vec<T>( Adder.Add( v1.x, v2.x ), Adder.Add( v1.y, v2.y ) );
}
and used:
public class IntAdder : IAdder<int>
{
public int Add( int t1, int t2 )
{
return t1 + t2;
}
}
class Program
{
static void Main( string[] args )
{
Vec<int> v1 = new Vec<int>( 4, 5 );
Vec<int> v2 = new Vec<int>( 6, 7 );
Vec<int> v3 = Vec<int>.Add( v1, v2, new IntAdder() );
Console.ReadLine();
}
}
While this works, there are obvious drawbacks – an extra implementation of the auxiliary interface has to be provided for any T you want to use your Vec class with. Also, the signature of the Add method is now rather clumsy.
Let’s then just start again:
public class Vec<T>
{
public T x { get; set; }
public T y { get; set; }
public Vec() { }
public Vec( T x, T y ) { this.x = x; this.y = y; }
public static Vec<T> Add( Vec<T> v1, Vec<T> v2 )
{
// ???
}
}
2 comments:
public class Vec
{
public T x { get; set; }
public T y { get; set; }
public Vec() { }
public Vec(T x, T y) { this.x = x; this.y = y; }
public static Vec Add(Vec v1, Vec v2)
{
dynamic a = v1;
dynamic b = v2;
return new Vec(a.x + b.x, a.y + b.y);
}
public override string ToString()
{
return x + " " + y;
}
}
class Program
{
static void Main(string[] args)
{
Vec a = new Vec(1,2);
Vec b = new Vec(3, 4);
Console.WriteLine(Vec.Add(a,b));
}
}
Is it correct?
yes indeed. the trick is to use dynamics. regards.
Post a Comment