将运算符与其他参数一起传递
Posted
技术标签:
【中文标题】将运算符与其他参数一起传递【英文标题】:Passing an operator along with other parameters 【发布时间】:2009-07-27 19:17:50 【问题描述】:我有一些非常低效的代码,当我使用“”操作以及各种变量和常量进行排列时,很多行出现了 4 次。似乎有一种方法可以编写一次函数并传入运算符以及必然变化的值和“ref”变量。我必须学习什么技术?有人建议使用“代表”,但我不知道如何以这种方式使用它们。这是在 C# 2.0 VS2005 中,但如果该技术是通用的并且也可以与 C++ 一起使用,那就太好了。
请求一些代码:以下以多种形式出现,带有不同的“”符号以及“+”和“-”符号的混合:
if (move[check].Ypos - move[check].height / 200.0D < LayoutManager.VISIO_HEIGHT - lcac_c.top)
move[check].Ypos = move[check].Ypos + adjust;
.
.
.
【问题讨论】:
你能发布一些代码吗? 我建议在http://refactormycode.com/ 上发布代码 sn-p。大多数提交有两个或三个备选方案。 有人可以格式化该代码吗?另外,你能给我们更多的代码吗?现在很难看出所有情况会发生什么变化——它会一直与move[check]
对抗吗?adjust
来自哪里?您当前对方法签名的猜测可能会有所帮助。
感谢 Rob 清理了我的代码的可见性! “adjust”是一个类变量,我根据屏幕分辨率和我正在演示程序的计算机来更改它。 move 是一个类的实例数组 在 4 个代码变体中的 2 个中,我会使用 Xpos,而不是 YPos。 4个中有2个有。任何带有 > 的东西都会在调整变量之前使用 +,反之亦然。另外,一个使用 lcac_c.top,一个使用 lcac_c.right,等等。我希望所有这些都被传入。
谢谢,我去看看那个网站!
【参考方案1】:
在 C++ 中,使用 std::less
和 std::greater
函子。这两个方法都继承了std::binary_function
,所以你的泛型函数应该接受这种类型的实例。
在 .NET 中,std::binary_function
的等价物是 Func<T, U, R>
。 std::less
和 std::greater
没有等价物,但创建它们相当简单。请参阅以下示例。
static class Functor
static Func<T, T, bool> Greater<T>()
where T : IComparable<T>
return delegate(T lhs, T rhs) return lhs.CompareTo(rhs) > 0; ;
static Func<T, T, bool> Less<T>()
where T : IComparable<T>
return delegate(T lhs, T rhs) return lhs.CompareTo(rhs) < 0; ;
注意,上面的代码使用 .NET 3.5 中的 Func<>
类。如果这不可接受,请考虑定义您自己的委托。
C++ 调用示例:
void DoWork(const std::binary_function<int, int, bool>& myOperator,
int arg1, int arg2)
if (myOperator(arg1, arg2)) /* perform rest of work */
void main()
DoWork(std::less<int>(), 100, 200);
DoWork(std::greater<int>(), 100, 200);
C# 调用示例:
void DoWork(Func<int, int, bool> myOperator, int arg1, int arg2)
if (myOperator(arg1, arg2)) /* perform rest of work */
void main()
DoWork(Functor.Less<int>(), 100, 200);
DoWork(Functor.Greater<int>(), 100, 200);
编辑:我更正了仿函数类的示例,因为将 运算符应用于泛型类型不起作用(与使用 C++ 模板的方式相同)。
【讨论】:
这个答案比我的要好得多。 在上面的 C# 示例中,Functor 在 .Net 2.0 中可用吗?我不能使上面的代码工作?我需要添加参考吗? 不,Functor 不是标准的 .NET 类——您需要自己编写。此外,.NET 2.0 不包含 Func(它位于 .NET 3.5 的 System.Core.dll 中),因此您需要使用 System.Predicate 来代替。【参考方案2】:在 C# 中,使用委托将“<
”和“>
”操作传递给正在执行工作的代码。
C# 示例:
public delegate bool BooleanOperatorDelegate(int a, int b)
class OperatorsImplementer
public bool OperatorLess(int a, int b)
return a < b;
class AnotherOperatorsImplementer
public bool OperatorLess(int a, int b)
return (a + 1) < (b - 1);
class OperatorUser
int DoSomethingObscene(int a, int b, BooleanOperatorDelegate operator)
if (operator(a, b))
return 5;
else
return -5;
您还应该检查作为参数获得的委托不为 NULL。
这是这样做的 C 方法:
bool (*operator_func)(float a, float b)
【讨论】:
惯用 C++ 实际上会使用函数对象而不是函数指针(特别是,这将允许使用std:less
和其他类似的普通函子)。【参考方案3】:
在Comparer类中定义枚举运算符后
public static class Comparer
public static bool IsTrue<T, U>(T value1, Operator comparisonOperator, U value2)
where T : U
where U : IComparable
switch (comparisonOperator)
case Operator.GreaterThan:
return value1.CompareTo(value2) > 0;
case Operator.GreaterThanOrEqual:
return value1.CompareTo(value2) >= 0;
case Operator.LessThan:
return value1.CompareTo(value2) < 0;
case Operator.LessThanOrEqual:
return value1.CompareTo(value2) <= 0;
case Operator.Equal:
return value1.CompareTo(value2) == 0;
default:
return false;
public enum Operator
GreaterThan = 1,
GreaterThanOrEqual = 2,
LessThan = 3,
LessThanOrEqual = 4,
Equal = 5
你可以这样打电话:
if (IsTrue(var1, Operator.GreaterThanOrEqual, var2))
Console.WriteLine("var1 is greater than var2");
else
Console
.WriteLine("Unfortunately var1 is not greater than or equal var2. Sorry about that.");
【讨论】:
请考虑添加一些细节和解释来支持您的回答,以帮助他人以上是关于将运算符与其他参数一起传递的主要内容,如果未能解决你的问题,请参考以下文章
在以抽象基类为参数的函数中将指针和赋值运算符与派生类一起使用