在C#中,什么';延迟初始化实例字段的最简单方法是什么?

在C#中,什么';延迟初始化实例字段的最简单方法是什么?,c#,asp.net,class,generics,C#,Asp.net,Class,Generics,我有一个包含5-6个字段的类,应该在构造函数运行后初始化一次 public OriginalFileProcessor(IConfigManager configManager) { this._configManager = configManager; this._field1 = this._configManager.GetAppSetting<int>ConfigKeys.Key1);

我有一个包含5-6个字段的类,应该在构造函数运行后初始化一次

 public OriginalFileProcessor(IConfigManager configManager)
        {
            this._configManager = configManager;
            this._field1 = this._configManager.GetAppSetting<int>ConfigKeys.Key1);
            this._field2 = this._configManager.GetAppSetting<int>ConfigKeys.Key2);
            this._field3 = this._configManager.GetAppSetting<int>ConfigKeys.Key3);
            this._field4 = this._configManager.GetAppSetting<int>ConfigKeys.Key4);
            this._field5 = this._configManager.GetAppSetting<int>ConfigKeys.Key5);
        }
公共原始文件处理器(IConfigManager configManager)
{
这。_configManager=configManager;
this.\u field1=this.\u configManager.GetAppSettingConfigKeys.Key1);
this.\u field2=this.\u configManager.GetAppSettingConfigKeys.Key2);
this.\u field3=this.\u configManager.GetAppSettingConfigKeys.Key3);
this.\u field4=this.\u configManager.GetAppSettingConfigKeys.Key4);
this.\u field5=this.\u configManager.GetAppSettingConfigKeys.Key5);
}
但是除了构造函数中的简单赋值之外,我不喜欢编写逻辑

例如,我不能对field1使用内联初始化,因为我不能使用那里的_configManager实例:

private int readonly _field1 = this._configManager.GetAppSetting<int>ConfigKeys.Key1);
private int readonly\u field1=this.\u configManager.getappsetingconfigkeys.Key1);
如果使用只读属性,则必须添加以下额外代码:

  private int? _field1;
        public int Property1
        {
            get
            {
                if (!this._field1.HasValue)
                {
                    this.__field1 = this._configManager.GetAppSetting<int>(Key1);    
                }
                return this._field1.Value;
            }
        }
private int_字段1;
公共物业1
{
得到
{
如果(!this.\u field1.HasValue)
{
this.\u field1=this.\u configManager.GetAppSetting(Key1);
}
返回此值。_field1.Value;
}
}
对于实例字段的后期初始化,有没有更简单的方法?

Lazy
是一个不错的选择

我通常使用的是以下内容

提供您的
\u字段*
是一个
可为空的

在你的财产里你可以做

return this.__field1 ?? (this.__field1 = this._configManager.GetAppSetting<int>(Key1));  
编辑2:

还有一个小测试来澄清懒惰行为:

public class DoLazy
{
    Lazy<int?> _field;
    public DoLazy()
    {
        // 'lazy' gets initialized - but `YourFieldInit` is not called yet.
        _field = new Lazy<int?>(() => YourFieldInit(""));
    }
    int Property
    {
        get
        {
            // `YourFieldInit` is called here, first time.
            return _field.Value ?? 0;
        }
    }
    int? YourFieldInit(string test)
    {   // breakpoint here
        return -1;
    }
    public static void Test()
    {
        var lazy = new DoLazy();
        int val1 = lazy.Property;
        var val = lazy.Property;
    }
}
公共类DoLazy
{
懒惰场;
公共场所
{
//“lazy”已初始化,但尚未调用“YourFieldInit”。
_field=newlazy(()=>YourFieldInit(“”);
}
int属性
{
得到
{
//“YourFieldInit”在这里第一次被调用。
返回_字段值??0;
}
}
int?YourFieldInit(字符串测试)
{//这里是断点
返回-1;
}
公共静态无效测试()
{
var lazy=new DoLazy();
int val1=lazy.Property;
var val=lazy.Property;
}
}
YourFieldInit
中放置一个断点,以查看何时实际调用它。
从您的主机调用
DoLazy.Test()

正如建议的那样,懒惰是一个很好的选择

我通常使用的是以下内容

提供您的
\u字段*
是一个
可为空的

在你的财产里你可以做

return this.__field1 ?? (this.__field1 = this._configManager.GetAppSetting<int>(Key1));  
编辑2:

还有一个小测试来澄清懒惰行为:

public class DoLazy
{
    Lazy<int?> _field;
    public DoLazy()
    {
        // 'lazy' gets initialized - but `YourFieldInit` is not called yet.
        _field = new Lazy<int?>(() => YourFieldInit(""));
    }
    int Property
    {
        get
        {
            // `YourFieldInit` is called here, first time.
            return _field.Value ?? 0;
        }
    }
    int? YourFieldInit(string test)
    {   // breakpoint here
        return -1;
    }
    public static void Test()
    {
        var lazy = new DoLazy();
        int val1 = lazy.Property;
        var val = lazy.Property;
    }
}
公共类DoLazy
{
懒惰场;
公共场所
{
//“lazy”已初始化,但尚未调用“YourFieldInit”。
_field=newlazy(()=>YourFieldInit(“”);
}
int属性
{
得到
{
//“YourFieldInit”在这里第一次被调用。
返回_字段值??0;
}
}
int?YourFieldInit(字符串测试)
{//这里是断点
返回-1;
}
公共静态无效测试()
{
var lazy=new DoLazy();
int val1=lazy.Property;
var val=lazy.Property;
}
}
YourFieldInit
中放置一个断点,以查看何时实际调用它。

从您的主机调用
DoLazy.Test()

@CuongLe为什么要删除您的答案?您的方法适用于可为空的值类型,我同意,但对于诸如字符串之类的引用类型,我不能依赖这种方法。初始化可能会返回null,它仍然有效,但在您的建议中,它将每次重试!我还想返回int而不是int?所以这里没办法。@TheLight这只是类似情况下的“最简单”解决方案。您的属性方法也不起作用(它会再次重试),所以我基本上就是这么做的。然后需要额外的“state”或标志。你可以
(int)
(内部)解析为int。@我用我认为足够的方式编辑的灯光case@CuongLe为什么要删除您的答案?您的方法适用于可为null的值类型,我同意,但对于诸如string之类的ref类型,我不能依赖这种方法。初始化可能会返回null,它仍然有效,但在您的建议中,它将每次重试!我还想返回int而不是int?所以这里没办法。@TheLight这只是类似情况下的“最简单”解决方案。您的属性方法也不起作用(它会再次重试),所以我基本上就是这么做的。然后需要额外的“state”或标志。您可以
(int)
(内部)解析为int。@我编辑的灯光,我认为可以满足这种情况