IConfiguration.Bind() 如何在没有 'out' 或 'ref' 参数的情况下在 .NET Core 中工作?
How IConfiguration.Bind() Works In .NET Core without 'out' or 'ref' in it's Arguments?
在 .NET Core 中,我们使用 IConfiguration
将配置绑定到实例。
var settings = new AppSettings();
Configuration.GetSection("AppSettings").Bind(settings);
为了在我的个人项目中创建类似 Bind() 的函数(针对不同的要求),我创建了一个这样的方法
public void BindOption(ref object instance)
{
...
}
然后像这样使用它
var settings = new AppSettings();
MyCustomStaticClass.BindOption(ref settings);
现在我的问题是
Bind()
函数如何在其参数中未明确提及 out
或 ref
的情况下工作?
听起来你误解了 ref
/out
- 当你使用引用类型 (class) 传递给方法,允许方法将对象的新实例分配给参数变量,并且调用代码可以看到更改。绝对不需要更改传递变量的某些数据内容。
我个人认为围绕这个的很多混淆来自短语“通过引用传递”,其中有一个以 ref
开头的词,巧合的是 ref
[ 中的 3 个字母=35=]
创建引用类型实例时:
Person john = new Person(){ Name = "John", Age = 27 };
您可以将其传递给方法:
void ChangeName(Person p){
p.Name = "Fred";
}
您无需指定 ref
即可更改并保留此名称
ChangeName(john);
Console.Print(john.Name); //Fred
在 C# 内部,假设您创建 John
并且 C# 分配一些内存,将名称放入其中并为您提供变量引用:
john --> { Name: "John", Age: 27 }
您调用该方法,C# 临时 生成另一个引用 p(因为该方法采用 Person p)
john --> { Name: "John", Age: 27 } <-- p
新引用,相同对象。您通过 p.Name 更改名称,原始对象受到影响
john --> { Name: "Fred", Age: 27 } <-- p
如果我们使用 ref
C# 没有创建新的引用,假设它只是暂时重命名我们现有的引用,然后在方法完成后将其重新命名
void ChangeName(ref Person p){
p.Name = "Fred";
}
john --> { Name: "John", Age: 27 } //start with
p --> { Name: "John", Age: 27 } //when start calling the method
p --> { Name: "Fred", Age: 27 } //method changes the person name
john --> { Name: "Fred", Age: 27 } //method exits, name is changed
我们这里从来不需要参考
不同的场景。人是不变的。更改名称的唯一方法是将其换成一个全新的对象
void ChangeName(Person p){
p = new Person { Name = "Fred", Age: 0 };
}
现在,这个需要参考。看看当我们没有 ref:
时会发生什么
john --> { Name: "John", Age: 27 }
john --> { Name: "John", Age: 27 } <-- p
john --> { Name: "John", Age: 27 } p --> { Name: "Fred", Age: 0 }
john --> { Name: "John", Age: 27 }
调用该方法对旧对象进行新引用,然后说 p = new...
将新引用重新附加到某个新对象,该对象在方法结束时立即销毁,没有任何改变
参考:
john --> { Name: "John", Age: 27 }
p --> { Name: "John", Age: 27 }
p --> { Name: "Fred", Age 0 }
john --> { Name: "Fred", Age 0 }
临时重命名该引用意味着当我们创建一个新对象并分配它时,原始调用代码也会遇到 new
仅当您将传入的内容设置为 new
并希望调用者看到新内容时才需要 ref
。大多数时候我们不需要它
脚注:out
与 ref
类似,只是编译器会检查该方法是否确实赋值。在将变量传递给方法时,您需要使用“out”或“ref”,因为它会引起您的注意“此方法可能会覆盖您传入的任何内容”(对于 ref)或“此方法肯定会覆盖您输入的任何内容”通过”(带出)
现代 .net 也有很少使用的 in
修饰符,它使编译器检查你没有为传入变量分配 new
任何东西(运行 方法结束时 Fred 丢失的非 ref 场景的风险)
在 .NET Core 中,我们使用 IConfiguration
将配置绑定到实例。
var settings = new AppSettings();
Configuration.GetSection("AppSettings").Bind(settings);
为了在我的个人项目中创建类似 Bind() 的函数(针对不同的要求),我创建了一个这样的方法
public void BindOption(ref object instance)
{
...
}
然后像这样使用它
var settings = new AppSettings();
MyCustomStaticClass.BindOption(ref settings);
现在我的问题是
Bind()
函数如何在其参数中未明确提及 out
或 ref
的情况下工作?
听起来你误解了 ref
/out
- 当你使用引用类型 (class) 传递给方法,允许方法将对象的新实例分配给参数变量,并且调用代码可以看到更改。绝对不需要更改传递变量的某些数据内容。
我个人认为围绕这个的很多混淆来自短语“通过引用传递”,其中有一个以 ref
开头的词,巧合的是 ref
[ 中的 3 个字母=35=]
创建引用类型实例时:
Person john = new Person(){ Name = "John", Age = 27 };
您可以将其传递给方法:
void ChangeName(Person p){
p.Name = "Fred";
}
您无需指定 ref
即可更改并保留此名称
ChangeName(john);
Console.Print(john.Name); //Fred
在 C# 内部,假设您创建 John
并且 C# 分配一些内存,将名称放入其中并为您提供变量引用:
john --> { Name: "John", Age: 27 }
您调用该方法,C# 临时 生成另一个引用 p(因为该方法采用 Person p)
john --> { Name: "John", Age: 27 } <-- p
新引用,相同对象。您通过 p.Name 更改名称,原始对象受到影响
john --> { Name: "Fred", Age: 27 } <-- p
如果我们使用 ref
C# 没有创建新的引用,假设它只是暂时重命名我们现有的引用,然后在方法完成后将其重新命名
void ChangeName(ref Person p){
p.Name = "Fred";
}
john --> { Name: "John", Age: 27 } //start with
p --> { Name: "John", Age: 27 } //when start calling the method
p --> { Name: "Fred", Age: 27 } //method changes the person name
john --> { Name: "Fred", Age: 27 } //method exits, name is changed
我们这里从来不需要参考
不同的场景。人是不变的。更改名称的唯一方法是将其换成一个全新的对象
void ChangeName(Person p){
p = new Person { Name = "Fred", Age: 0 };
}
现在,这个需要参考。看看当我们没有 ref:
时会发生什么john --> { Name: "John", Age: 27 }
john --> { Name: "John", Age: 27 } <-- p
john --> { Name: "John", Age: 27 } p --> { Name: "Fred", Age: 0 }
john --> { Name: "John", Age: 27 }
调用该方法对旧对象进行新引用,然后说 p = new...
将新引用重新附加到某个新对象,该对象在方法结束时立即销毁,没有任何改变
参考:
john --> { Name: "John", Age: 27 }
p --> { Name: "John", Age: 27 }
p --> { Name: "Fred", Age 0 }
john --> { Name: "Fred", Age 0 }
临时重命名该引用意味着当我们创建一个新对象并分配它时,原始调用代码也会遇到 new
仅当您将传入的内容设置为 new
并希望调用者看到新内容时才需要 ref
。大多数时候我们不需要它
脚注:out
与 ref
类似,只是编译器会检查该方法是否确实赋值。在将变量传递给方法时,您需要使用“out”或“ref”,因为它会引起您的注意“此方法可能会覆盖您传入的任何内容”(对于 ref)或“此方法肯定会覆盖您输入的任何内容”通过”(带出)
现代 .net 也有很少使用的 in
修饰符,它使编译器检查你没有为传入变量分配 new
任何东西(运行 方法结束时 Fred 丢失的非 ref 场景的风险)