Reputation: 71
In the following code, IPoint
and IPointGroup
are abbreviated versions of existing interfaces that define how data is shared between many parts of a large application.
The abbreviated generic implementations of RefPoint<T>
and PointGroup<T>
are used in a new subsystem that deals with large volumes of points so consideration needs to be given to minimizing the duplication of and casting required to work with the points.
At the bottom of the code, two problems are illustrated:
IPointGroup<T>
generic interface.I'd appreciate suggestions/improvements to the approach I've taken. I'm quite new to C# generics so I may be missing something obvious.
using System;
namespace Generic
{
public interface IPoint { }
public interface IPointGroup
{ void Add( IPoint x );
}
public interface IPointGroup<T> where T : IPoint
{ void Add( T x );
}
public class RefPoint<T> : IPoint
{
public int X, Y;
T _refersTo;
public RefPoint( int x, int y, T refersTo )
{
X = x;
Y = y;
_refersTo = refersTo;
}
public T refersTo()
{ return _refersTo;
}
}
public class PointGroup<T> : IPointGroup where T : IPoint
{
internal void Add( T y )
{
Console.WriteLine("In Add( T y )");
}
public void Add( IPoint x )
{
Console.WriteLine("In Add(IA x)");
Add((T)x);
}
}
public class Swerve : IPoint { }
public class HardBrake : IPoint { }
public class StopSign { };
class Program
{
static void Main( string[] args )
{
PointGroup<Swerve> swerves = new PointGroup<Swerve>();
PointGroup<HardBrake> hardBrakes = new PointGroup<HardBrake>();
PointGroup<RefPoint<StopSign>> stopSigns = new PointGroup<RefPoint<StopSign>>();
PointGroup<IPoint> all = new PointGroup<IPoint>();
Swerve s = new Swerve();
swerves.Add(s);
HardBrake h = new HardBrake();
hardBrakes.Add(h);
StopSign ss = new StopSign();
RefPoint<StopSign> ss_ref = new RefPoint<StopSign>(1,1,ss);
stopSigns.Add(ss_ref);
// Problem #1: Each element is cast
all.Add(s);
all.Add(h);
all.Add(ss_ref);
// Problem #2: Can't cast as follows
// IPointGroup<Swerve> iSwerves = (IPointGroup<Swerve>)swerves;
// IPointGroup<HardBrake> iHardBrakes = (IPointGroup<HardBrake>)hardBrakes;
// IPointGroup<RefPoint<StopSign>> iStopSigns = (IPointGroup<RefPoint<StopSign>>) stopSigns;
// IPointGroup<IPoint> iAll = (IPointGroup<IPoint>)all;
}
}
}
Upvotes: 2
Views: 633
Reputation: 27964
Here you implement IPointGroup
:
public class PointGroup<T> : IPointGroup where T : IPoint
while you probably meant IPointGroup<T>
:
public class PointGroup<T> : IPointGroup<T> where T : IPoint
Also, IPointGroup
and IPointGroup<T>
are not related anyhow in your design. The common approach when a non-generic and generic version of an interface is needed, is that the generic one inherits the non-generic one; hence:
public interface IPointGroup<T> : IPointGroup where T : IPoint
Plus to benefit from the generic version primarily, consider implementing the non-generic one explicitly, like this:
public class PointGroup<T> : IPointGroup<T> where T : IPoint
{
// implicit implementation of IPointGroup<T>.Add(T)
public void Add(T y) { … }
// explicit implementation of IPointGroup.Add(IPoint)
void IPointGroup.Add(IPoint x)
{
Add((T)x);
}
}
Upvotes: 2