泛型类的字段约束 - C#

时间:2017-04-15 16:55:27

标签: c# unity3d monogame

我想在C#中创建一个使用Point对象的库,但是在C#中有很多框架都有很多Point的实现:Point,Vector2f(unity),Vector2f(monogame),Vector3f ...我希望我的图书馆可以与所有人一起工作。

唯一的限制是对象具有属性X和Y,并且X和Y必须实现IComparable接口。问题是,如果不使用反射,我就无法找到一种方法(不是我认为最好的方法)。

我不希望所有类Point继承自我的界面,但我希望它们有2个字段/成员X和Y.

有办法吗?像

customersRef.child(u.id!).child(("deals" as NSString)).childByAutoId().setValue("true") { error, dbRef in
                print("Is now always called")

        }

2 个答案:

答案 0 :(得分:2)

您无法在编译时检查它,因为如果您不希望所有类继承公共接口或创建大量适配器,则C#无法满足您的需求。

在运行时,Reflection是您实现目标的唯一方法。反思并不总是那么糟糕,它只取决于你如何实现事物。实际上,反思的第一个问题是表现。

如果您在每次通话中使用它,可能会带来很大的开销。但是,如果你在静态构造函数中检查它,那么检查将只应用一次,并且在标称执行时没有任何开销就可以完成工作。

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());
    }
}

答案 1 :(得分:1)

你在这里谈论的是Duck Typing。 (如果它看起来像一只鸭子,像鸭子那样嘎嘎叫,它一定是鸭子,对吗?)。

C#并不完全支持传统意义上的鸭子打字。大多数强类型编译语言没有此功能(afaik)。但是,正如您在维基百科上看到的那样,您可以使用dynamic代替。

正如已经提到的,反射实际上是唯一的方式,我理解它的方式dynamic实际上只是在引擎盖下使用反射。如果表现是一个问题(在这种情况下可能是这样),你应该尝试一些不同的方法和措施。 quick google似乎表明它非常复杂,但至少值得一试。