c#泛型函数
本文关键字:函数 泛型 | 更新日期: 2023-09-27 18:05:39
寻求c#泛型方面的帮助。我正在Unity3D中工作,并且正在滚动BiLerp功能,因为Unity3D没有一个。
public Vector3 BiLerp(Vector2 _uv, Vector3 _00, Vector3 _01, Vector3 _10, Vector3 _11)
{
return _00 * (1 - _uv.x) * (1 - _uv.y) +
_10 * _uv.x * (1 - _uv.y) +
_01 * _uv.y * (1 - _uv.x) +
_11 * _uv.x * _uv.y;
}
但是,我想使这个函数更健壮一点。
- 我想让它通用,这样它就可以接受任何类型,可以乘以一个float
- 我不确定我是否应该使这个静态。我假设它不使用任何成员变量,那么是的。如果该类存储在静态中,该类将仅用于unity (Matrix2x2)等省略的数学助手。 在这种情况下c#的const是如何工作的?
- 在c++中,我将通过引用传递参数。如果我正确地假设c#已经这样做了吗?ref关键字是另一个黑魔法工具吗?
如果有任何其他建议,请不要客气。我只在c#工作了6个星期,现在可以使用任何建议。
-
虽然可以通过传递一个执行乘法的委托来实现,但它会慢得多。实际上,我认为你最好写多个重载,而不是。
-
是的,你应该,你也应该把它放在一个静态类。(恕我直言!)我本来打算建议你把它作为一个扩展方法,但是经过反思,它有太多的参数,使它变得那么有用。
-
c# const与c++ const类似,但一般的共识是它们只能是私有的(或者可能是内部的)。
-
实际上,Vector2和Vector3是结构体,所以它们是按值传递的。如果您想通过引用传递它们,请使用
ref
关键字:public Vector3 BiLerp( ref Vector2 _uv, ref Vector3 _00, ref Vector3 _01, ref Vector3 _10, ref Vector3 _11)`
然而,这样做只有两个原因(对于结构体):
-
因为你想改变传入的原始值
-
通过传递一个引用(即c++术语中的指针)来加速。
第一个在您的代码中不适用,第二个对于这样小的结构体似乎没有意义(事实上,所有结构体都应该很小,所以它几乎不适用于设计良好的结构体)。
不幸的是,c#的泛型类型系统不支持这种约束。这是c#团队考虑过的一个经常被要求的特性,但它需要在底层CLR类型系统中做大量的工作。将来有可能实现,但如果我是你,我不会屏息等待那一天。我想把它变成通用的,这样它就可以接受任何可以乘以浮点数的类型
我不确定我是否应该使它静态。我假设它不使用任何成员变量,那么是的。
是的,让它变成静态的。
如果存储它的类也是静态的,则该类将仅用于数学帮助。
是的。
c#的const在这种情况下是如何工作的?
c# const与c++ const不同;这就简单多了。在c#中,const字段或local只是编译时常量数或字符串的名称,仅此而已。(好吧,你也可以有const的引用类型,但它必须是空的,所以这不是那么有趣。)这里没有你在c#中看到的"这是一个引用,但你不能调用任何改变它的方法"的规则。
最佳实践是首先使所有值类型不可变,因此c++风格的const并不是真正必要的。
将字段标记为"只读"使其只能在构造函数中更改。
在c++中,我将通过引用传递参数。我假设c#已经做到这一点是正确的吗?
。值类型按值传递。
ref关键字是其他一些黑魔法的工具?
ref关键字就像c++中的引用:使一个变量成为另一个的别名。在c#中,您通常只在希望改变调用者提供的变量的情况下使用。正如我之前所说的,c#没有c++的"const引用"的概念,但是由于c#中的值类型应该很小,因此按值传递的效率很高,因此通常不需要"const引用"的概念来说明"我想通过引用传递这个以提高性能,但实际上不改变变量"。
1)我想把它模板化,这样它就可以接受任何可以乘以浮点数的类型
不确定当前c#中泛型的实现是否可行。不能定义T where T : float
。编译器会告诉你only class or interface could be specified as constraint
.
2)我不确定是否应该使此静态. ...
我不会使一个类静态,因为你有一个静态方法在它。我看不出你定义的方法有什么问题。由于它不使用成员,所以将其设置为静态是有意义的(看起来像一个helper方法)。您也可以将其作为马修斯回答中建议的扩展方法。比如:
public static class Vector2Ext
{
public static Vector3 BiLerp(
this Vector2 _uv,
Vector3 _00,
Vector3 _01,
Vector3 _10,
Vector3 _11)
{
// your implementation
}
}
这样您就可以将方法BiLerp
作为Vector2上的方法调用。
Vector2 vector2 = ...;
vector2.BiLerp(_00, _01, _10, _11);
如果以这种方式设计它是有意义的,那么在这种情况下你可能会做出最好的判断。
3) c#的const在这种情况下是如何工作的?
有点模糊,不确定你的意思。MSDN在这里有帮助吗?
4)在c++中,我将通过引用传递参数。如果我正确地假设c#已经这样做了吗?ref关键字是另一个黑魔法工具吗?
这本身就是一个话题。如果使用ref
关键字,则传递类型作为引用。如果VectorXD
是不可变类型,这是有意义的。如果需要在调用端返回valuetype的值,则需要通过ref传递它们。看看你的代码,我解释它为你传递一些值,用它们来计算一个Vector3D
,并返回。我不认为这里需要ref
。但也许我又误解了你的问题。也许MSDN有助于理解ref
的用法。
c#没有模板,因为它们在c++中是众所周知的。术语是generics
,它们比c++代码中的模板更受约束。对于您所需要的,不可能从float
类型继承,也不可能将泛型约束放入数字类型,因为float
是ValueType
。c#(以及一般的。net)中的值类型不能通过类型继承来扩展。
建议您可以直接使用float
或double
。c#从所有其他数字类型(可能除了decimal
)自动强制转换为float
和double
。