我需要调用作为参数传递的委托方法,但由于此参数是可选的,我想将默认值设置为在“目标”类中实现的方法。
这是一个几乎按预期工作的例子:
public class AgeCalculator
{
public void SetAge(Client client, Func<int, int> getAge = default(Func<int, int>))
{
client.Age = getAge != default(Func<int, int>) ? getAge(client.Id) : this.getAge(client.Id);
}
private int getAge(int clientId) {
return 10;
}
}
然后..
class Program
{
static void Main(string[] args)
{
AgeCalculator calculator = new AgeCalculator();
Client cli1 = new Client(1, "theOne");
calculator.SetAge(cli1);//Sets 10
calculator.SetAge(cli1, getAge);//Sets 5
}
private static int getAge(int clientId) {
return 5;
}
}
问题现在;什么是必须设置的默认值,以避免询问委托值?
尝试了“public void SetAge(客户端客户端,Func getAge = this.getAge)”但没有运气。
AgeCalculator.getAge上是否需要标记或不同的定义?我应该使用动态方法吗?
提前致谢。
注意:真实场景涉及面向TDD的项目中更复杂的逻辑,这是一个总结情况的示例。
答案 0 :(得分:7)
方法参数的默认值必须是编译时常量。编写default(Func<...>)
只是null
的详细语法,这是引用类型的默认值(作为委托,Func
是引用类型),并且您可以在此使用唯一的默认值上下文。
但是,您可以通过为该方法提供两个重载的传统方式做得更好:
public void SetAge(Client client)
{
// Select any default value you want by calling the other overload with it
SetAge(client, this.getAge);
}
public void SetAge(Client client, Func<int, int> getAge)
{
client.Age = getAge(client.Id);
}
答案 1 :(得分:1)
这基本上就是你要求的,唯一的事情是VS提供的提示不会显示如果没有使用null,函数将被用作默认值。如果这不是问题,那么这个解决方案在逻辑上就像你将要获得的那样接近。
public class AgeCalculator
{
public void SetAge ( Client client , Func<int , int> getAge = null)
{
// assigns this.getAge to getAge if getAge is null
getAge = getAge ?? this.getAge;
client.Age = getAge( client.Id );
}
private int getAge ( int clientId )
{
return 10;
}
}
如果要动态更改默认设置器,还可以使用允许插入变量方法的内容。它只是另一种方式相同的逻辑,如果您知道连续多次使用相同的函数,这将是有益的。
public class AgeCalculator
{
public void SetAge ( Client client )
{
client.Age = GetAge( client.Id );
}
private Func<int,int> _getAge;
public Func<int,int> GetAge
{
private get
{
if(_getAge == null)
_getAge = getAge;
return _getAge;
}
set
{
if(value == null)
_getAge = getAge;
else
_getAge = value;
}
}
private int getAge ( int clientId )
{
return 10;
}
}
//assume we are in main
var cl = new Agecalculator();
var client = new Client(1,"theOne");
var client2 = new Client(2,"#2");
cl.SetAge(client); //set 10
cl.GetAge = getAge;
cl.SetAge(client); //set 5
cl.SetAge(client2); //set 5