Reputation: 93
I am trying to implement a "Dimension" unit which is a generic type, but which can be stored in a list alongside other Dimensions of different type.
What I want to be able to do is to store a list of these "Dimensions" in one list (so, for example, store Dimension<int>
alongside Dimension<string>
, in the same list), and I'd also like to be able to compare Dimensions of the same type (so, for example, compare an instance of Dimension<string>
with another instance of Dimension<string>
, but never compare an instance of Dimension<int>
with an instance of Dimension<string>
).
I've read (here: C# - Multiple generic types in one list) that that a (the?) way to store different generic types in one list is by using abstract classes or interfaces. This lets me achieve the first goal of storing them in one list. However, I want to iterate over the list and compare, ultimately computing the total "distance" between two different lists (with distance being defined on a per-type basis).
I'd probably get confused reading this too, so I've taken a screenshot of a really basic structure and implementation, and displaying the compile time error I am receiving.
You can see roughly what I want to achieve in the bottom "Implementation" class's method - and you can also see the specific problem I'm running into while trying to implement the interface.
So I guess my questions are:
How can I get around the error I'm receiving so that implementing the interface works? Why does it require an Interface as the parameter rather than allowing an implementation of the interface?
And I guess more generally - is there a better way to achieve what I want to do? Is what I want to do achievable/does it make sense?
Upvotes: 0
Views: 102
Reputation: 387617
So this is your interface and your attempted implementation:
interface IDimension
{
double DistanceBetween(IDimension d);
}
public class Dimension<T> : IDimension
{
public T Data { get; private set; }
public Dimension(T data)
{
Data = data;
}
public double DistanceBetween(Dimension<T> otherPoint)
{
return 0;
}
}
Now interfaces are exact, they show exactly what and how you need to implement the interface members. In this case, you absolutely need a method DistanceBetween
that not only takes a Dimension<T>
object, but a IDimension
object.
The interface says that you need to be able to pass any IDimension
object to that method, so just accepting one subtype Dimension<T>
is not enough.
So first of all, you need to implement that method directly. You can however include an overload that works for the particular type Dimension<T>
in order to provide special behavior.
public double DistanceBetween(IDimension otherPoint)
{
if (otherPoint is Dimension<T>)
return DistanceBetween((Dimension<T>)otherPoint);
// general implementation, only using what the interface provides
return 0;
}
public double DistanceBetween(Dimension<T> otherPoint)
{
return otherPoint.Data - Data; // or whatever
}
Upvotes: 1
Reputation: 14350
The implementation signature must match interface signature. In this case that means that function DistanceBetween
must accept any IDimension
, not just a specific implementation of it.
The interface promises that DistanceBetween
will accept any IDimension
as an argument. The Dimension<T>
's failed attempt will only accept one specific implementation of IDimension
. To implement it properly, you must change the signature in Dimension<T>
to public double DistanceBetween(IDimension anyVarName)
.
Upvotes: 2