泛型 class 的字段约束 - C#
Fields constraints for generic class - C#
我想在 C# 中创建一个库,它对 Point 对象进行一些处理,但在 C# 中有很多框架实现了很多 Point :Point、Vector2f (unity)、Vector2f (monogame) , Vector3f ... 我希望我的库能与它们一起工作。
唯一的限制是对象具有属性 X 和 Y,并且 X 和 Y 必须实现 IComparable 接口。问题是我找不到不使用反射的方法来做到这一点(我认为这不是最好的方法)。
我不希望所有 class 点都继承自我的界面,但我希望它们有 2 个字段/成员 X 和 Y。
有办法吗?喜欢
class MyAlgo<T> : where T has X and Y properties {}
您无法在编译时检查它,因为如果您不希望所有 class 继承通用接口或创建大量适配器,C# 无法满足您的需求。
在运行时,反射是唯一的方法。反思并不总是那么糟糕,它只取决于你如何实施。的确,第一个反思的问题就是性能。
如果您在每次调用中都使用它,可能会带来很大的开销。但是,如果您在静态构造函数中检查它,例如,检查将只应用一次并且在名义执行时没有任何开销地完成工作。
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());
}
}
你这里说的叫Duck Typing。 (长得像鸭子,叫起来也像鸭子,那肯定是鸭子吧?)
C# 并不完全支持传统意义上的鸭子类型。大多数强类型编译语言没有此功能(afaik)。但是,正如您在维基百科上看到的那样,您可以改用 dynamic
。
如前所述,反射确实是唯一的方法,我理解它的方式 dynamic
实际上只是在幕后使用反射。如果性能是一个问题(在这种情况下可能是这样),您应该尝试几种不同的方法和衡量标准。 quick google 似乎暗示它相当复杂,但至少值得一试。
我想在 C# 中创建一个库,它对 Point 对象进行一些处理,但在 C# 中有很多框架实现了很多 Point :Point、Vector2f (unity)、Vector2f (monogame) , Vector3f ... 我希望我的库能与它们一起工作。
唯一的限制是对象具有属性 X 和 Y,并且 X 和 Y 必须实现 IComparable 接口。问题是我找不到不使用反射的方法来做到这一点(我认为这不是最好的方法)。
我不希望所有 class 点都继承自我的界面,但我希望它们有 2 个字段/成员 X 和 Y。
有办法吗?喜欢
class MyAlgo<T> : where T has X and Y properties {}
您无法在编译时检查它,因为如果您不希望所有 class 继承通用接口或创建大量适配器,C# 无法满足您的需求。
在运行时,反射是唯一的方法。反思并不总是那么糟糕,它只取决于你如何实施。的确,第一个反思的问题就是性能。
如果您在每次调用中都使用它,可能会带来很大的开销。但是,如果您在静态构造函数中检查它,例如,检查将只应用一次并且在名义执行时没有任何开销地完成工作。
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());
}
}
你这里说的叫Duck Typing。 (长得像鸭子,叫起来也像鸭子,那肯定是鸭子吧?)
C# 并不完全支持传统意义上的鸭子类型。大多数强类型编译语言没有此功能(afaik)。但是,正如您在维基百科上看到的那样,您可以改用 dynamic
。
如前所述,反射确实是唯一的方法,我理解它的方式 dynamic
实际上只是在幕后使用反射。如果性能是一个问题(在这种情况下可能是这样),您应该尝试几种不同的方法和衡量标准。 quick google 似乎暗示它相当复杂,但至少值得一试。