0

I'd like to make a library in C# which does some works with Point object but in C# there is a lot of frameworks with a lot of implementation of Point : Point, Vector2f (unity), Vector2f (monogame), Vector3f ... and I'd like that my library works with all of them.

The only constraint is that the object has properties X and Y and that X and Y must implement IComparable interface. The problem is that I can't found a way to do that without using reflexion (not the best way I think).

I don't want that all class Point inherite from my interface but I'd like them to have 2 fields / members X and Y.

Is there a way to do that ? Like

class MyAlgo<T> : where T has X and Y properties {}
Quentin
  • 144
  • 8

2 Answers2

2

You can't check it at compile time since C# is not able to cover your need if you don't want all class inherits a common interface or create a lot of adapters.

At runtime Reflection is your single way to do it. Reflection is not always so bad, it depends only how you implements things. Indeed, the first issue of reflection is performance.

If you use it in each call, it can introduce a significant overhead. But if you check it in your static constructor for example, the check will be applied only once and do the job without any overhead at nominal execution.

class MyAlgo<T>
{
    static private Func<T, int> X;
    static private Func<T, int> Y;

    static MyAlgo()
    {
        //check here!
        var type = typeof(T);
        var x = type.GetProperty("X");
        if (x == null) { throw new NotSupportedException($"missing X property in { type }"); }
        var y = type.GetProperty("Y");
        if (y == null) { throw new NotSupportedException($"missing Y property in { type }"); }

        // you can store delegate to retreive X & Y in static fields.
        MyAlgo<T>.X = Delegate.CreateDelegate(typeof(Func<T, int>), x.GetGetMethod());
        MyAlgo<T>.Y = Delegate.CreateDelegate(typeof(Func<T, int>), y.GetGetMethod());
    }
}
Tony THONG
  • 772
  • 5
  • 11
  • A great workaround to not having traits (as in Rust) in C#. I had to do the same a few times, when writing algorithms that work with both my own data types and third party data types. – Sergey.quixoticaxis.Ivanov Apr 26 '17 at 12:37
1

What you're talking about here is called Duck Typing. (if it looks like a duck, and quacks like a duck, it must be a duck, right?).

C# doesn't exactly support duck typing in the traditional sense. Most strongly typed compiled languages don't have this feature (afaik). However, as you can see on Wikipedia you might be able to use dynamic instead.

As already mentioned, reflection is really the only way and the way I understand it dynamic is really just using reflection under the hood. If performance is a concern (which it probably is in this case) you should try a few different approaches and measure. A quick google seems to suggest that it's quite complicated, but it's at least worth try.

Community
  • 1
  • 1
craftworkgames
  • 9,437
  • 4
  • 41
  • 52