Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有条件地传递命名参数_C#_C# 4.0_Named Parameters - Fatal编程技术网

C# 有条件地传递命名参数

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

我有一个将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 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());
}