সি # অলস স্বয়ংক্রিয় বৈশিষ্ট্যগুলি লোড হয়েছে


102

সি # তে,

কোনও নির্দিষ্ট ডিফল্ট মান সহ একটি অলস লোড স্বয়ংক্রিয় সম্পত্তিতে কোনও স্বয়ংক্রিয় সম্পত্তি কীভাবে পরিবর্তন করার কোনও উপায় আছে?

মূলত, আমি এটি চালু করার চেষ্টা করছি ...

private string _SomeVariable

public string SomeVariable
{
     get
     {
          if(_SomeVariable == null)
          {
             _SomeVariable = SomeClass.IOnlyWantToCallYouOnce();
          }

          return _SomeVariable;
     }
}

আলাদা কিছুতে, যেখানে আমি ডিফল্ট নির্দিষ্ট করতে পারি এবং এটি বাকীটি স্বয়ংক্রিয়ভাবে পরিচালনা করে ...

[SetUsing(SomeClass.IOnlyWantToCallYouOnce())]
public string SomeVariable {get; private set;}

@ গাবে: নোট করুন ক্লাসটি কেবল একবার কল করা হবে যদি তা কখনই শূন্য হয় না।
রেডফিল্টার

আমি আবিষ্কার করেছি যে ... এটি
সিঙ্গলটন

উত্তর:


113

কোন নেই. স্বতঃ-প্রয়োগকৃত বৈশিষ্ট্যগুলি কেবলমাত্র বৈশিষ্ট্যগুলির সর্বাধিক বুনিয়াদ বাস্তবায়নের জন্য কাজ করে: গেটর এবং সেটার সহ ব্যাকিং ফিল্ড। এটি এই ধরণের কাস্টমাইজেশন সমর্থন করে না।

তবে আপনি Lazy<T>এই প্যাটার্নটি তৈরি করতে 4.0 টাইপ ব্যবহার করতে পারেন

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

এই কোডটি _someVariableপ্রথমে Valueঅভিব্যক্তিটি বলা হওয়ার সময়টি আলস্যভাবে গণনা করবে । এটি কেবল একবার গণনা করা হবে এবং ভবিষ্যতের Valueসম্পত্তি ব্যবহারের জন্য মানটি ক্যাশে করবে


4
আসলে, এটি আমার কাছে দেখে মনে হচ্ছে যেন অলস সিঙ্গলটন প্যাটার্নটি প্রয়োগ করে। এটি আমার লক্ষ্য নয় ... আমার লক্ষ্যটি হচ্ছে একটি অলস বোঝা সম্পত্তি তৈরি করা যা অলসভাবে তাত্ক্ষণিকভাবে তবে সেই শ্রেণীর যে উদাহরণে এটি বাস করে তা নিষ্পত্তি করে। অলসভাবে সেভাবে পারফর্ম করছে বলে মনে হয় না।
ctorx

19
@ctorx অলসটির সিঙ্গলটন প্যাটার্নের কোনও সম্পর্ক নেই। এটি আপনি যা করতে চান ঠিক তা করে।
ব্যবহারকারী 247702

8
দ্রষ্টব্য, SomeClass.IOnlyWantToCallYouOnceআপনার উদাহরণে কোনও ক্ষেত্র আরম্ভকারীর সাথে ব্যবহার করতে অবশ্যই স্থির থাকতে হবে।
rory.ap

দুর্দান্ত উত্তর। ভিজ্যুয়াল স্টুডিওর স্নিপেটের জন্য আমার উত্তরটি দেখুন আপনি যদি অনেক অলস বৈশিষ্ট্য আশা করেন তবে আপনি ব্যবহার করতে পারেন।
জেফ্রিল

40

সম্ভবত আপনি সবচেয়ে সংক্ষিপ্ত পেতে পারেন নাল-কোয়েলসিং অপারেটরটি ব্যবহার করা:

get { return _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce()); }

10
ক্ষেত্রে IOnlyWantToCallYouOnceরিটার্ন nullএটি একাধিকবার কল করবে।
জারেডপাড়

9
নাল-কোয়েলসিং অপারেটর ব্যবহার করার সময়, উপরের উদাহরণটি ব্যর্থ হবে। সঠিক বাক্য গঠনটি হ'ল: _SomeVariable ?? ( _SomeVariable = SomeClass.IOnlyWantToCallYouOnce() );- বন্ধ হয়ে থাকলে সেটটি চারপাশে বন্ধনীর সংযোজনটি লক্ষ্য করুন _SomeVariableit
মেট্রো স্মুরফ

এটি সেরা বিকল্প। প্রথমে আমি ব্যবহার করেছি Lazy<>, তবে আমাদের উদ্দেশ্যে এটি আরও ভাল কাজ করেছে। সর্বশেষ সি # এর সাথে এটি আরও সংক্ষিপ্তভাবেও লেখা => _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce());যেতে পারে যা প্রথম চেহারা থেকে কেউ কেউ খেয়াল করবেন না তা হ'ল অপারেটর ডান হাতের ক্রিয়াকলাপটি মূল্যায়ন করে এবং তার ফলাফলটি ফিরিয়ে দেয়
রানিংলভ্লান

অলস থ্রেড নিরাপদ, এটি নয়
PLopes

15

সি # 6 এ এক্সপ্রেশন বোডেড অটো-প্রোপার্টি নামে একটি নতুন বৈশিষ্ট্য রয়েছে যা আপনাকে এটিকে কিছুটা পরিষ্কার করে লেখার অনুমতি দেয়:

public class SomeClass
{ 
   private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);

   public string SomeVariable 
   {
      get { return _someVariable.Value; }
   }
}

এখন এই হিসাবে লেখা যেতে পারে:

public class SomeClass
{
   private Lazy<string> _someVariable = new Lazy<string>(SomeClass.IOnlyWantToCallYouOnce);

   public string SomeVariable => _someVariable.Value;
}

কোডের শেষ বিভাগে, সূচনাটি আসলে অলস নয়। IOnlyWantToCallYouOnceক্লাস তাত্ক্ষণিক প্রতিবার নির্মাণের সময় ডাকা হবে।
টম ব্লডজেট

সুতরাং অন্য শব্দে এই অলস বোঝা হয় না?
Zapnologica

@ জাপনোলিকা আমার আগের উত্তরটি কিছুটা ভুল ছিল তবে আমি এটি আপডেট করেছি। SomeVariableঅলস বোঝা।
আলেকজান্ডার ডার্ক

এই উত্তরটি এক্সপ্রেশন বডিড অটো-প্রোপার্টিগুলির জন্য একটি পিচের মতো আরও পড়ে।
ছোট এন্ডিয়ান

@ আবেলআরচার একটি নতুন ভাষার বৈশিষ্ট্যটি দেখানো এখন একটি পিচ?
আলেকজান্ডার ডার্ক

5

এর মতো নয়, বৈশিষ্ট্যের জন্য প্যারামিটারগুলির মান স্থির থাকতে হবে, আপনি কোড (এমনকি স্থির কোড) কল করতে পারবেন না।

আপনি তবে পোস্টশার্পের দিকগুলি দিয়ে কিছু বাস্তবায়ন করতে সক্ষম হতে পারেন।

ওদের বের কর:

পোস্টশার্প


5

আপনার সমস্যার সমাধানের জন্য আমার বাস্তবায়ন এখানে। মূলত ধারণাটি এমন একটি সম্পত্তি যা প্রথম অ্যাক্সেসে কোনও ফাংশন দ্বারা সেট করা হবে এবং পরবর্তী অ্যাকসেসগুলি প্রথমটির মতো একই রিটার্ন মান প্রদান করবে।

public class LazyProperty<T>
{
    bool _initialized = false;
    T _result;

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

তারপরে ব্যবহার করতে:

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

চারপাশে ফাংশন পয়েন্টারটি পাস করার ওভারহেড অবশ্যই রয়েছে, তবে এটি আমার জন্য কাজ করে এবং বার বার পদ্ধতিটি চালনার সাথে তুলনায় আমি খুব বেশি ওভারহেড লক্ষ্য করি না।


কনস্ট্রাক্টরের কাছে ফাংশনটি দেওয়া কি আরও বেশি অর্থবোধ করে না? আপনি প্রতিটি বার এটি ইনলাইন তৈরি করবেন না, এবং আপনি এটি প্রথমবার ব্যবহারের পরে তা নিষ্পত্তি করতে পারেন।
মিক্কেল আর লুন্ড

@ লন্ড.মিক্কেল হ্যাঁ, এটিও কার্যকর হবে। উভয় পদ্ধতির জন্য ক্ষেত্রে ব্যবহার হতে পারে।
deepee1

4
আপনি যদি কন্সট্রাক্টরের কাছে ফাংশনটি পাস করেন, অনেকটা। নেট এর অলস ক্লাসের মতো, তখন পাস করা ফাংশনটি অচল হতে হবে, আমি জানি এটি অনেক ক্ষেত্রে আমার নকশাকে ফিট করে না।
ক্রাঞ্চি

@ মিকেলআর.লুন্ড কখনও কখনও আপনি কনস্ট্রাক্টরে কিছু কোড প্রয়োগ করতে চান না তবে কেবল চাহিদা অনুসারে (এবং ফলাফলটি একটি ব্যাকিং ফিল্ডের আকারে ক্যাশে করুন)
ম্যামেসস্ট্যাক

4

অপারেটর ?? = সি # 8.0 এবং তারপরে ব্যবহার করে উপলভ্য, তাই এখন আপনি আরও সংক্ষিপ্ত করতে পারেন:

private string _someVariable;

public string SomeVariable => _someVariable ??= SomeClass.IOnlyWantToCallYouOnce();


3

আমি এই ধারণার একটি বড় অনুরাগী, এবং নীচের সি # স্নিপেট অফার করতে চাই যা আমি প্রপ্লেজি.স্নিপেট বলেছি ((আপনি স্নিপেট ম্যানেজারের কাছ থেকে পেতে পারেন এটি স্ট্যান্ডার্ড ফোল্ডারে আমদানি করতে পারেন বা এটিকে পেস্ট করতে পারেন)

এটির ফলাফলের একটি নমুনা এখানে:

private Lazy<int> myProperty = new Lazy<int>(()=>1);
public int MyProperty { get { return myProperty.Value; } }

এখানে স্নিপেট ফাইল সামগ্রী: (প্রোপলজি.স্নিপেট হিসাবে সংরক্ষণ করুন)

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>proplazy</Title>
            <Shortcut>proplazy</Shortcut>
            <Description>Code snippet for property and backing field</Description>
            <Author>Microsoft Corporation</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>The variable backing this property</ToolTip>
                    <Default>myVar</Default>
                </Literal>
                <Literal>
                    <ID>func</ID>
                    <ToolTip>The function providing the lazy value</ToolTip>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>

            </Declarations>
            <Code Language="csharp"><![CDATA[private Lazy<$type$> $field$ = new Lazy<$type$>($func$);
            public $type$ $property$ { get{ return $field$.Value; } }
            $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

আমি সেট myPropertyকরতে চাই readonly, কেবল নিরাপদে
থাকব

2

খাঁটি সি # দিয়ে এটি সম্ভব বলে আমি মনে করি না। তবে আপনি পোস্টশার্পের মতো আইএল পুনরায় লেখক ব্যবহার করে এটি করতে পারেন । উদাহরণস্বরূপ এটি বৈশিষ্ট্যের উপর নির্ভর করে ফাংশনগুলির আগে এবং পরে আপনাকে হ্যান্ডলার যুক্ত করতে দেয়।


2

আমি এটি এর মতো করেছিলাম:

public static class LazyCachableGetter
{
    private static ConditionalWeakTable<object, IDictionary<string, object>> Instances = new ConditionalWeakTable<object, IDictionary<string, object>>();
    public static R LazyValue<T, R>(this T obj, Func<R> factory, [CallerMemberName] string prop = "")
    {
        R result = default(R);
        if (!ReferenceEquals(obj, null))
        {
            if (!Instances.TryGetValue(obj, out var cache))
            {
                cache = new ConcurrentDictionary<string, object>();
                Instances.Add(obj, cache);

            }


            if (!cache.TryGetValue(prop, out var cached))
            {
                cache[prop] = (result = factory());
            }
            else
            {
                result = (R)cached;
            }

        }
        return result;
    }
}

এবং পরে আপনি এটি পছন্দ মতো ব্যবহার করতে পারেন

       public virtual bool SomeProperty => this.LazyValue(() =>
    {
        return true; 
    });

আমি এই প্রসঙ্গে "এটি" কীভাবে ব্যবহার করব?
রিয়ারা

@ রিরা মানে কি? ঠিক নিয়মিত সম্পত্তি হিসাবে। উদাহরণস্বরূপ public ISet<String> RegularProperty {get;set} public string CalculatedProperty => this.LazyValue(() => { return string.Join(",", RegularProperty.ToArray()); });
আলেকজান্ডার জুবান

0

https://github.com/bcuff/ অটোলিজি আপনাকে এ জাতীয় কিছু দেওয়ার জন্য ফডি ব্যবহার করে

public class MyClass
{
    // This would work as a method, e.g. GetSettings(), as well.
    [Lazy]
    public static Settings Settings
    {
        get
        {
            using (var fs = File.Open("settings.xml", FileMode.Open))
            {
                var serializer = new XmlSerializer(typeof(Settings));
                return (Settings)serializer.Deserialize(fs);
            }
        }
    }

    [Lazy]
    public static Settings GetSettingsFile(string fileName)
    {
        using (var fs = File.Open(fileName, FileMode.Open))
        {
            var serializer = new XmlSerializer(typeof(Settings));
            return (Settings)serializer.Deserialize(fs);
        }
    }
}

0
[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;
}

এবং আমি সুরকার মত কল

result.RaporBilgisi = new ExchangeProgramPersonAllDataModel.RaporImza(() => _reportConfigService.GetReportLayout(documentTypeId));

4
যদিও এটি লেখকদের প্রশ্নের উত্তর দিতে পারে, এতে কিছু ব্যাখ্যাকারী শব্দ এবং ডকুমেন্টেশনের লিঙ্কের অভাব রয়েছে। কাঁচা কোড স্নিপেটগুলি এর চারপাশে কিছু বাক্যাংশ ব্যতীত খুব বেশি কার্যকর নয়। আপনি কীভাবে একটি ভাল উত্তর লিখতে পারেন তা খুব সহায়ক find আপনার উত্তর সম্পাদনা করুন।
হেলো

0

আপনি যদি অলস সূচনা করার সময় কোনও কনস্ট্রাক্টর ব্যবহার করেন তবে নিম্নলিখিত এক্সটেনশনগুলিও সহায়ক হতে পারে

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));
}

ব্যবহার

    private Dictionary<string, object> _cache;

    public Dictionary<string, object> Cache => New.Lazy(ref _cache);

                    /* _cache ?? (_cache = new Dictionary<string, object>()); */

4
আপনার সাহায্যকারীকে ব্যবহার করার কি কোনও সুবিধা আছে LazyInitializer.EnsureInitialized()? কারণ আমি যা বলতে পারি তার থেকে উপরের কার্যকারিতা ছাড়াও LazyInitializerত্রুটি পরিচালনার পাশাপাশি সিঙ্ক কার্যকারিতা সরবরাহ করে। LazyInitializer উত্স কোড
semaj1919
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.