C# Lazy Loaded Automatic Properties

前端 未结 12 2136
执笔经年
执笔经年 2020-12-04 11:08

In C#,

Is there a way to turn an automatic property into a lazy loaded automatic property with a specified default value?

Essentially, I am trying to turn th

相关标签:
12条回答
  • 2020-12-04 11:44

    Operator ??= is available using C# 8.0 and later, so you can now do it even more concise:

    private string _someVariable;
    
    public string SomeVariable => _someVariable ??= SomeClass.IOnlyWantToCallYouOnce();
    
    
    0 讨论(0)
  • 2020-12-04 11:46

    Not like that, parameters for attributes must be constant in value, you cannot call code (Even static code).

    You may however be able to implement something with PostSharp's Aspects.

    Check them out:

    PostSharp

    0 讨论(0)
  • 2020-12-04 11:49

    No there is not. Auto-implemented properties only function to implement the most basic of properties: backing field with getter and setter. It doesn't support this type of customization.

    However you can use the 4.0 Lazy<T> type to create this pattern

    private Lazy<string> _someVariable =new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);
    public string SomeVariable => _someVariable.Value;
    

    This code will lazily calculate the value of _someVariable the first time the Value expression is called. It will only be calculated once and will cache the value for future uses of the Value property

    0 讨论(0)
  • 2020-12-04 11:49
    [Serializable]
    public class RaporImza
    {
        private readonly Func<ReportConfig> _getReportLayout;
        public RaporImza(Func<ReportConfig> getReportLayout)
        {
            _getReportLayout = getReportLayout;
        }
    
        private ReportConfig _getReportLayoutResult;
        public ReportConfig GetReportLayoutResult => _getReportLayoutResult ?? (_getReportLayoutResult = _getReportLayout());
    
        public string ImzaAtanKisiAdi => GetReportLayoutResult.ReportSignatureName;
    
        public string ImzaAtanKisiUnvani => GetReportLayoutResult.ReportSignatureTitle;
        public byte[] Imza => GetReportLayoutResult.ReportSignature;
    }
    

    and i call like bellow

    result.RaporBilgisi = new ExchangeProgramPersonAllDataModel.RaporImza(() => _reportConfigService.GetReportLayout(documentTypeId));
    
    0 讨论(0)
  • 2020-12-04 11:50

    Here's my implementation of a solve to your problem. Basically the idea is a property that will be set by a function at first access and subsequent accesses will yield the same return value as the first.

    public class LazyProperty<T>
    {
        bool _initialized = false;
        T _result;
    
        public T Value(Func<T> fn)
        {
            if (!_initialized)
            {
                _result = fn();
                _initialized = true;
            }
            return _result;
        }
     }
    

    Then to use:

    LazyProperty<Color> _eyeColor = new LazyProperty<Color>();
    public Color EyeColor
    { 
        get 
        {
            return _eyeColor.Value(() => SomeCPUHungryMethod());
        } 
    }
    

    There is of course the overhead of passing the function pointer around, but it does the job for me and I don't notice too much overhead compared to running the method over and over again.

    0 讨论(0)
  • 2020-12-04 11:53

    If you use a constructor during lazy initialization, following extensions may be helpful too

    public static partial class New
    {
        public static T Lazy<T>(ref T o) where T : class, new() => o ?? (o = new T());
        public static T Lazy<T>(ref T o, params object[] args) where T : class, new() =>
                o ?? (o = (T) Activator.CreateInstance(typeof(T), args));
    }
    

    Usage

        private Dictionary<string, object> _cache;
    
        public Dictionary<string, object> Cache => New.Lazy(ref _cache);
    
                        /* _cache ?? (_cache = new Dictionary<string, object>()); */
    
    0 讨论(0)
提交回复
热议问题