我正在学习C#,我感兴趣的一个领域是委托功能。以下代码使用它们将函数应用于范围中的每个数字[start,limit [在求和之前]。为清楚起见,这是一个相当简单的例子。
// function passing a delegate function
public override void solveProblem() {
int squareOfSum = (int) Math.Pow(Library.Math.sumRange(1, 101), 2);
int sumOfSquares = Library.Math.sumRange(1, 101, new Func<double, double, double>(Math.Pow), 2);
this.solution = (squareOfSum - sumOfSquares).ToString();
}
// function that accepts / uses delegate function
static public int sumRange(int start, int limit, Delegate operation, params object[] args) {
int sum = 0;
for (int current = start; current < limit; current++) {
// add the current number in the range as an arguement
object[] newArgs = new object[args.Length + 1];
newArgs[0] = current;
args.CopyTo(newArgs, 1);
// sum the result of the operation (delegate function)
sum += Convert.ToInt32(operation.DynamicInvoke(newArgs));
}
return sum;
}
我的具体问题是:
是否可以使用动态委托函数(接受具有未知类型的参数的可变长度列表)但强制委托函数返回特定类型?使用非动态委托函数,您可以设置返回类型,但也必须设置参数的数量及其类型。
使用DynamicInvoke比使用非动态委托功能慢多少?
处理参数的最佳方法是什么(我接受其他参数的列表,并在其中添加使用委托需要添加的函数的任何参数)?
我是否需要声明'new Func(Math.Pow)'来传递幂函数,或者是否有办法只传递Math.Pow(并且隐式传递返回类型和参数)
我查看了C#docs和this StackOverflow question以了解如何使用委托功能,我只想了解更多相关信息。
谢谢!
jtfairbank
答案 0 :(得分:2)
是否可以使用动态委托函数(接受a 具有未知类型的参数的可变长度列表)但强制 委托函数返回特定类型?使用非动态委托 函数你设置一个返回类型,但也必须设置数量 参数及其类型。
你没有“强制”函数返回一些东西。该函数返回一些东西或它不返回一些东西。该功能“强迫”你接受某些东西:-)(或忽略它)
您可以通过DynamicInvoke
调用动态委托,然后将返回值转换为您知道委托返回的内容(或者将其保留为object
)。我说“你知道你的代理人返回了什么”但实际情况稍微复杂一些:对于价值类型,你必须将返回值精确地转换为用作返回值的类型,否则你将获得InvalidCastException
。对于引用类型,您可以使用返回的对象的接口或基类(对于Nullable类型有一些例外)
使用DynamicInvoke比使用非动态委托函数慢多少?
我已经测试了一个void Do()
方法(可能是最简单的方法,没有参数装箱),时间差是贬义的。让我们说400x :-)在http://ideone.com/f34cj,它介于70x和150x之间。
我是否需要声明'new Func(Math.Pow)'来传递幂函数,或者是否有办法只传递Math.Pow(并且隐式传递返回类型和参数)?
创建新的Func
/ Action
委托是正确的道路。
一般而言,正确的解决方案并非您正在做的事情。正确的解决方案就像LINQ一样。例如:
int pow = 2;
Func<int, int> myFunc = p => (int)Math.Pow(p, pow);
var listOfNumbers = Enumerable.Range(1, 100);
var result = listOfNumbers.Sum(p => myFunc(p));
现在,您有一个委托(myFunc
),它接受一个数字并返回该数字的平方(并注意通过“闭包”它在pow
附近关闭)(如果您不这样做)知道封闭是什么,尝试用谷歌函数把这个词放在谷歌中。作为IEnumerable<int>
的数字列表,您可以按myFunc
“转换”这些数字的总和。
答案 1 :(得分:1)
读取LINQ - IEnumerable的使用产生了更紧凑的代码。
即。 Enumrable.Range(http://msdn.microsoft.com/en-us/library/system.linq.enumerable.range.aspx)和Enumerable.Aggregate(http://msdn.microsoft.com/en-us/library/bb548651.aspx)的组合正是您想要实现的目标:
var sum = Enumerable.Range(start,limit).Aggregate((s, cur)=> s+cur);
var sumSq = Enumerable.Range(start,limit).Aggregate((s, cur)=> s+ cur * cur);