简体   繁体   中英

Generic type for property of an Interface

I have a set of data structures that looks like follows:

  • different DataPoints that implement the IDataPoint interface (to secure the existence of a value and a coordinate point)
  • each DataPoint might have different coordinate types (2D, 3D etc)
  • the coordinates are stored in generic tuples that all implement the interface ITuple (to secure the existence of at least one (X) coordinate)

My problem is, that I haven't found out how to make the Coord property of the IDataPoint generic so that coordinates can be either 2d or 3d (or sth else if needed later on). This is my attempt:

public interface IDataPoint
{ 
    float Value { get; }
    <Tuple> Coords { get; } where <ITuple> : ITuple

    string ToString();
}

Where is my error or is this simply not possible?

Rest of the code

public interface ITuple<T>
{
    T X { get; }

    string ToString();
}

public struct TwoTuple<T> : ITuple<T>
{
    public T X { get; }
    public T Y { get; }
    public TwoTuple(T x, T y)
    {
        X = x;
        Y = y;
    }

    public override string ToString()
    {
        return "(" + X + ", " + Y + ")";
    }
}

public struct ThreeTuple<T> : ITuple<T>
{
    public T X { get; }
    public T Y { get; }
    public T Z { get; }
    public ThreeTuple(T x, T y, T z)
    {
        X = x;
        Y = y;
        Z = z;
    }

    public override string ToString()
    {
        return "(" + X + ", " + Y + ", " + Z + ")";
    }
}

public interface IDataPoint
{ 
    float Value { get; }
    <Tuple> Coords { get; } where <ITuple> : ITuple

    string ToString();
}

public struct BarDataPoint : IDataPoint
{
    public TwoTuple<float> Coords { get; }
    public float Value { get; }
    public BarDataPoint(TwoTuple<float> Coords, float Value)
    {
        this.Coords = Coords;
        this.Value = Value;
    }

    public override string ToString()
    {
        return "Coordinates: " + Coords + "; Value: " + Value;
    }
}

public struct ScatterDataPoint : IDataPoint
{
    public ThreeTuple<float> Coords { get; }
    public float Value { get; }
    public ScatterDataPoint(ThreeTuple<float> coords, float value)
    {
        this.Coords = coords;
        this.Value = value;
    }

    public override string ToString()
    {
        return "Coordinates: " + Coords + "; Value: " + Value;
    }
}

Interface

public interface IDataPoint<TTuple>
{
    float Value { get; }
    TTuple Coords { get; }

    string ToString();
}

Usage

 public struct BarDataPoint : IDataPoint<ThreeTuple<float>>
{
    public float Value { get; }

    public ThreeTuple<float> Coords { get; set; }

    public BarDataPoint(ThreeTuple<float> Coords, float Value)
    {
        this.Coords = Coords;
        this.Value = Value;
    }

    public override string ToString()
    {
        return "Coordinates: " + Coords + "; Value: " + Value;
    }
}

Do it like you did it in your ITuple interface by providing the generics and its constraints in the interface declaration:

public interface IDataPoint<T,T2> where T : ITuple<T2>
{ 
    float Value { get; }
    T Coords { get; } 

    string ToString();
}

Your Coords property now has the type T , and T has to implement the interface ITuple<T2> . Your class BarDataPoint should be defined like this:

public struct BarDataPoint : IDataPoint<TwoTuple<float>,float>

You'll have to tell the compiler the generic type of ITuple<T> twice. Online demo: https://dotnetfiddle.net/CYw1bR

What you can do is this:

public interface IDataPoint 
{
    float Value { get; }
    ITuple Coords { get; }

    string ToString();
}

you dont need generics. ITuple is general purpose base implementation for tuples. these are all derived from ITuple

System.Tuple<T1>
System.Tuple<T1,T2>
System.Tuple<T1,T2,T3>
System.Tuple<T1,T2,T3,T4>
System.Tuple<T1,T2,T3,T4,T5>
System.Tuple<T1,T2,T3,T4,T5,T6>
System.Tuple<T1,T2,T3,T4,T5,T6,T7>
System.Tuple<T1,T2,T3,T4,T5,T6,T7,TRest>
System.ValueTuple
System.ValueTuple<T1>
System.ValueTuple<T1,T2>
System.ValueTuple<T1,T2,T3>
System.ValueTuple<T1,T2,T3,T4>
System.ValueTuple<T1,T2,T3,T4,T5>
System.ValueTuple<T1,T2,T3,T4,T5,T6>
System.ValueTuple<T1,T2,T3,T4,T5,T6,T7>
System.ValueTuple<T1,T2,T3,T4,T5,T6,T7,TRest>

ITuple Documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM