C# 有条件地传递命名参数
我有一个将3个命名参数带入构造函数的结构C# 有条件地传递命名参数,c#,c#-4.0,named-parameters,C#,C# 4.0,Named Parameters,我有一个将3个命名参数带入构造函数的结构 public struct MyData { private readonly double _value1; private readonly double _value2; private readonly double _value3; public MyData( double value1 = 1.0, double value2 = 2.0, double va
public struct MyData
{
private readonly double _value1;
private readonly double _value2;
private readonly double _value3;
public MyData(
double value1 = 1.0,
double value2 = 2.0,
double value3 = 3.0)
{
_value1 = value1;
_value2 = value2;
_value3 = value3;
}
}
创建类的方法调用接收三个可为null的double,我只想在可为null的double不为null时使用它们来创建MyData类
public MyData CreateMyData(double? value1, double? value2, double? value3)
{
MyData myData;
if (value1.HasValue)
{
if (value2.HasValue)
{
if (value3.HasValue)
{
myData = new MyData(value1, value2, value3);
}
else
{
myData = new MyData(value1, value2);
}
}
else
{
if (value3.HasValue)
{
myData = new MyData(value1, value3: value3);
}
else
{
myData = new MyData(value1);
}
}
}
else
{
if (value2.HasValue)
{
if (value3.HasValue)
{
myData = new MyData(value2: value2, value3: value3);
}
else
{
myData = new MyData(value2: value2);
}
}
else
{
if (value3.HasValue)
{
myData = new MyData(value3: value3);
}
else
{
myData = new MyData();
}
}
}
return myData;
}
有没有更好的方法来编写这个方法而不修改MyData类?也就是说,我可以有条件地传递命名参数吗?或者我可以传递一个表示默认命名参数值的指示符吗?也许您只需要:
return new MyData(value1 ?? 1.0, value2 ?? 2.0, value3 ?? 3.0);
?
这样,您就可以直接传递null
s,而不会受到错误的影响
此外,如果您决定更改默认值,即使不重新编译此代码的所有用户,它也可以工作。检查此项
var t = typeof (MyData);
var c = t.GetConstructor(new Type[] { typeof(double), typeof(double), typeof(double)});
var p = c.GetParameters();
return new MyData(value1 ?? p[0].DefaultValue, value2 ?? p[1].DefaultValue, value3 ?? p[2].DefaultValue);
public MyData CreateMyData(double? value1, double? value2, double? value3)
{
var ss= typeof(MyData).GetConstructor(new Type[]{typeof(double),typeof(double),typeof(double)});
var parametesr = ss.GetParameters();
return new MyData(value1 ?? Convert.ToDouble(parametesr[0].DefaultValue), value2 ?? Convert.ToDouble(parametesr[1].DefaultValue), value3 ?? Convert.ToDouble(parametesr[2].DefaultValue));
}
要做到这一点,您需要延迟绑定。通过开源框架,您可以访问所需的DLR功能
使用impromptu接口;
...
公共MyData创建MyData(双值1、双值2、双值3)
{
var arg=InvokeArg.Create;
var argList=新列表();
如果(值1.HasValue)
argList.Add(arg(“value1”,value1));
if(value2.HasValue)
argList.Add(arg(“value2”,value2));
如果(值3.HasValue)
argList.Add(arg(“value3”,value3));
返回Impromptu.InvokeConstructor(typeof(MyData),argList.ToArray());
}
这种方式涉及到调用方法控制默认值。我希望默认值的责任与MyData类共存。这意味着可以修改MyData类中的默认值,而无需查找对MyData类的所有引用。不过感谢您的建议:-)好吧,您可以将CreateMyData
设置为MyData
的静态方法(如果允许您修改该类)。@noob:这个理由没有意义。可选参数和默认参数在调用站点解析,而不是在被调用方的站点解析。如果您更改默认参数,但不将消费者代码与MyData
一起重新编译,消费者代码仍将使用原始默认值调用,而不是新的默认值。啊,对了,这很有趣。即使我仍然需要重新编译所有引用,也最好在MyData类中定义它们。非常感谢你告诉我这件事,这是我以前不知道的。他要求的解决方案不涉及修改MyData
@中间,啊,我没有注意到。这是一个非常有趣的答案。如果我当时正在创建第三方使用的类,那么在使用命名值类型参数时,这通常是设计类的更好方法吗?@Noob,如果将来可以更改默认值,那么绝对是这样。如果不是这样的话,那么可能是的。你为什么不想修改MyData
?在大多数情况下,我想知道是否有一种不修改MyData的方法。我会问这个问题,以防遇到MyData不在我的控制之下的情况(例如,第三方库或其他东西)。至少现在,大多数.Net库都不使用可选参数。仅供参考,在您的示例中,由于MyData是一个结构
而不是类
,请务必注意CreateMyData2(null,null,null)
将返回MyData,其中\u值1
,\u值2
,\u值3
等于零。不管怎样,结构都有默认构造函数,并且优先于可选参数构造函数。是的,这看起来是修改MyData类或在调用类中硬编码默认值的唯一选择。
public MyData CreateMyData(double? value1, double? value2, double? value3)
{
var ss= typeof(MyData).GetConstructor(new Type[]{typeof(double),typeof(double),typeof(double)});
var parametesr = ss.GetParameters();
return new MyData(value1 ?? Convert.ToDouble(parametesr[0].DefaultValue), value2 ?? Convert.ToDouble(parametesr[1].DefaultValue), value3 ?? Convert.ToDouble(parametesr[2].DefaultValue));
}
using ImpromptuInterface;
...
public MyData CreateMyData(double? value1, double? value2, double? value3)
{
var arg = InvokeArg.Create;
var argList = new List<Object>();
if(value1.HasValue)
argList.Add(arg("value1",value1));
if(value2.HasValue)
argList.Add(arg("value2",value2));
if(value3.HasValue)
argList.Add(arg("value3",value3));
return Impromptu.InvokeConstructor(typeof(MyData), argList.ToArray());
}