gpt4 book ai didi

.net - 默认参数和反射 : if ParameterInfo. IsOptional 那么DefaultValue总是可靠的吗?

转载 作者:行者123 更新时间:2023-12-02 09:30:39 25 4
gpt4 key购买 nike

我正在研究如何定义 ParameterInfo.IsOptional (我正在向内部 IOC 框架添加默认参数支持),在我看来,当为 true 时,无法保证ParameterInfo.DefaultValue(或者实际上ParameterInfo.RawDefaultValue)实际上是要应用的默认值。

如果你看MSDN example given for IsOptional ,在 IL 中似乎可以定义一个可选参数,但不提供默认值(假设必须显式提供 ParameterAttributes.HasDefault)。 IE。可能会导致参数类型为 Int32ParameterInfo.IsOptional 为 true,但 ParameterInfo.DefaultValue 为 null 的情况。

我的语言是 C#,因此我可以研究编译器将要做的事情。基于此,我可以进行如下简单的测试(parameter 这里是一个 ParameterInfo 实例,该方法旨在返回一个实例,用作运行时参数参数):

if(no_config_value)
{
if(!parameter.IsOptional) throw new InvalidOperationException();
//it's optional, so read the Default
return parameter.DefaultValue;
}
else
return current_method_for_getting_value();

但我认为某些语言(我希望在 IL 级别上做到这一点,而不是仅仅基于某个特定编译器的功能)可以将责任归咎于调用者确定要使用的默认值,如果是这样,则需要按顺序使用 default(parameter.ParameterType)

这就是它变得更有趣的地方,因为如果没有默认值,则 DefaultValue 显然是 DBNull.Value (根据 the documentation for RawValue )。如果参数的类型为 objectIsOptional==true,那就不好了!

经过更多挖掘,我希望解决此问题的可靠方法是物理读取 ParameterInfo.Attributes 成员,首先单独读取位标志检查ParameterAttributes.Optional然后检查ParameterAttributes.Default。仅当两者都存在时,读取ParameterInfo.DefaultValue才是正确的。

我将开始围绕此进行编码和编写测试,但我希望有人具有更多 IL 知识,可以证实我的怀疑,并希望确认这对于任何基于 IL 的都是正确的语言(从而避免需要模拟不同语言的库负载!)。

最佳答案

我的问题的简短答案是否定的 - 只是因为 IsOptional 为 true 并不意味着 DefaultValue 实际上包含真正的默认值。我在问题文本中进一步的假设是正确的(.Net 文档确实以一种迂回的方式解释了这一点)。本质上,如果存在默认值,那么调用者应该使用它,否则调用者应该提供自己的默认值。参数的Attributes 用于确定是否存在默认值。

这就是我所做的。

假设存在以下方法:

/* wrapper around a generic FastDefault<T>() that returns default(T) */
public object FastDefault(Type t) { /*elided*/ }

然后给出一个特定的参数和提供的参数值的字典(来自配置):

public object GetParameterValue(ParameterInfo p, IDictionary<string, object> args)
{
/* null checks on p and args elided - args can be empty though */
object argValue = null;
if(args.TryGetValue(p.Name, out argValue))
return argValue;
else if(p.IsOptional)
{
//now check to see if a default is supplied in the IL with the method
if((p.Attributes & ParameterAttributes.HasDefault) ==
ParameterAttributes.HasDefault)
return p.DefaultValue; //use the supplied default
else
return FastDefault(p.ParameterType); //use the FastDefault method
}
else //parameter requires an argument - throw an exception
throw new InvalidOperationException("Parameter requires an argument");
}

然后我在构造函数和方法上测试了这个逻辑,如下所示:

public class Test
{
public readonly string Message;
public Test(string message = "hello") { Message = message; }
}

I.E,除了可选参数之外还提供了默认值(程序正确地落入到达 ParameterInfo.DefaultValue 的分支)。

然后,在回答我问题的另一部分时,我意识到在 C# 4 中我们可以使用 OptionalAttribute生成一个可选参数没有默认值:

public class Test2
{
public readonly string Message;
public Test2([OptionalAttribute]string message) { Message = message; }
}

程序再次正确地落入执行 FastDefault 方法的分支。

(在这种情况下,C# 也将使用类型的默认值作为此参数的实参)

我认为这涵盖了所有内容 - 它在我尝试过的所有内容上都运行良好(我很高兴尝试让重载解析感觉正确,因为我的 IOC 系统总是使用等效的命名参数 - 但 C# 4 规范对此有所帮助)。

关于.net - 默认参数和反射 : if ParameterInfo. IsOptional 那么DefaultValue总是可靠的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9977530/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com