Hy-
Hy-

Reputation: 93

Why is this not sufficient to implement the interface?

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.

http://i.imgur.com/OBQDVBj.png

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

Answers (2)

poke
poke

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

Shlomo
Shlomo

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

Related Questions