কিছু সি # ল্যাম্বডা এক্সপ্রেশন স্থির পদ্ধতিতে সংকলন করে কেন?


122

আপনি নীচের কোডটিতে দেখতে পাচ্ছেন, আমি একটি ঘোষণা করেছি Action<> বস্তুকে ভেরিয়েবল হিসাবে ।

কেউ দয়া করে আমাকে জানতে দিন কেন এই ক্রিয়া পদ্ধতির প্রতিনিধি স্থির পদ্ধতির মতো আচরণ করে?

কেন ফিরে আসে trueএটি নিম্নলিখিত কোডটিতে ?

কোড:

public static void Main(string[] args)
{
    Action<string> actionMethod = s => { Console.WriteLine("My Name is " + s); };

    Console.WriteLine(actionMethod.Method.IsStatic);

    Console.Read();
}

আউটপুট:

নমুনার উদাহরণ আউটপুট

উত্তর:


153

এটি খুব সম্ভবত কারণ কোনও বন্ধকরণ নেই, উদাহরণস্বরূপ:

int age = 25;
Action<string> withClosure = s => Console.WriteLine("My name is {0} and I am {1} years old", s, age);
Action<string> withoutClosure = s => Console.WriteLine("My name is {0}", s);
Console.WriteLine(withClosure.Method.IsStatic);
Console.WriteLine(withoutClosure.Method.IsStatic);

এই ইচ্ছার আউটপুট falseজন্য withClosureএবং trueজন্যwithoutClosure

আপনি যখন ল্যাম্বডা এক্সপ্রেশন ব্যবহার করেন, কম্পাইলারটি আপনার পদ্ধতিটি ধারণ করতে একটি সামান্য শ্রেণি তৈরি করে, এটি নিম্নলিখিতগুলির মতো এমন কিছু সংকলন করে (প্রকৃত বাস্তবায়ন সম্ভবত সামান্য পরিবর্তিত হয়):

private class <Main>b__0
{
    public int age;
    public void withClosure(string s)
    {
        Console.WriteLine("My name is {0} and I am {1} years old", s, age)
    }
}

private static class <Main>b__1
{
    public static void withoutClosure(string s)
    {
        Console.WriteLine("My name is {0}", s)
    }
}

public static void Main()
{
    var b__0 = new <Main>b__0();
    b__0.age = 25;
    Action<string> withClosure = b__0.withClosure;
    Action<string> withoutClosure = <Main>b__1.withoutClosure;
    Console.WriteLine(withClosure.Method.IsStatic);
    Console.WriteLine(withoutClosure.Method.IsStatic);
}

ফলস্বরূপ Action<string>দৃষ্টান্তগুলি প্রকৃতপক্ষে এই উত্পন্ন ক্লাসগুলির পদ্ধতিগুলির দিকে নির্দেশ করতে পারে।


4
+1 টি। নিশ্চিত করতে পারেন - কোনও বন্ধ না করে তারা staticপদ্ধতিগুলির জন্য নিখুঁত প্রার্থী ।
সাইমন হোয়াইটহেড

3
আমি কেবল এই পরামর্শটি দিতে যাচ্ছিলাম যে এই প্রশ্নের কিছুটা প্রসারণ প্রয়োজন, আমি ফিরে এসেছি এবং এটি ছিল। সংবেদনশীল কভারগুলির নীচে কী করছে তা দেখতে খুব তথ্যপূর্ণ - দুর্দান্ত।
লিথ

4
বাস্তবে Ildasmকী চলছে তা বোঝার জন্য @ লিয়াথ সত্যিই দরকারী, আমি ছোট নমুনাগুলি পরীক্ষা করার জন্য ILট্যাবটি ব্যবহার করি tend LINQPad
লুকুয়েড

@ লুকাজয়েড আপনি কি দয়া করে আমাদের জানান যে আপনি এই সংকলক আউটপুটটি কীভাবে পেয়েছেন? ILDASM এ জাতীয় আউটপুট দেবে না .. কোনও সরঞ্জাম বা সফ্টওয়্যার দ্বারা?
নুনু

8
@ নুনু এই উদাহরণে, আমি ILট্যাবটি ব্যবহার করেছি LINQPadএবং সি # কে অনুমান করেছি। সংকলিত আউটপুটটির আসল সি # সমতুল্য হওয়ার জন্য কয়েকটি বিকল্প ব্যবহার করা হবে ILSpyবা Reflectorসংকলিত সমাবেশে আপনাকে সম্ভবত কয়েকটি বিকল্প অক্ষম করতে হবে যা ল্যাম্বডাস প্রদর্শন করার চেষ্টা করবে এবং সংকলক উত্পন্ন ক্লাসগুলি নয়।
লুকুয়েড

20

"ক্রিয়া পদ্ধতি" বাস্তবায়নের পার্শ্ব প্রতিক্রিয়া হিসাবে স্থির। এটি কোনও বেনামে চালিত ভেরিয়েবল ছাড়া একটি বেনামি পদ্ধতির একটি মামলা। যেহেতু কোনও ক্যাপচারড ভেরিয়েবল নেই, সাধারণভাবে স্থানীয় ভেরিয়েবলগুলির জন্য পদ্ধতির কোনও অতিরিক্ত আজীবন প্রয়োজনীয়তা নেই। যদি এটি অন্যান্য স্থানীয় ভেরিয়েবলগুলি রেফারেন্স করে থাকে তবে এর জীবনকাল সেই সমস্ত অন্যান্য ভেরিয়েবলগুলির জীবনকাল পর্যন্ত প্রসারিত হবে (সেকেন্ডের এল। এল ..7.৩, স্থানীয় ভেরিয়েবল এবং সেকেন্ড দেখুন। এন .৫.৫.১, ক্যাপচারিত বহিরাগত ভেরিয়েবলগুলি সি # 5.0 স্পেসিফিকেশনে )।

মনে রাখবেন যে সি # স্পেসিফিকেশন কেবল বেনামে পদ্ধতিগুলিকে "এক্সপ্রেশন ট্রি" তে রূপান্তরিত করার বিষয়ে কথা বলে, "বেনামে শ্রেণি" না। এক্সপ্রেশন ট্রি অতিরিক্ত সি # শ্রেণি হিসাবে উপস্থাপিত হতে পারে, উদাহরণস্বরূপ, মাইক্রোসফ্ট সংকলকটিতে, এই বাস্তবায়ন প্রয়োজন হয় না (সেকেন্ড দ্বারা স্বীকৃত হিসাবে এম। 5.3 সি # 5.0 নির্দিষ্টকরণে)। সুতরাং, বেনামে ফাংশন স্থির কিনা তা অপরিজ্ঞাত। অধিকন্তু, বিভাগের কে .6 এক্সপ্রেশন গাছের বিবরণ হিসাবে অনেক খোলা ছেড়ে দেয় open


2
+1 এই আচরণটি সম্ভবত বর্ণিত কারণে, নির্ভর করা উচিত নয়; এটি একটি বাস্তবায়ন বিস্তারিত।
লুকুয়েড

18

ডেলিগেট ক্যাচিং আচরণটি রোজলিনে পরিবর্তন করা হয়েছিল। পূর্বে, যেমনটি বলা হয়েছে, কোনও ল্যাম্বডা এক্সপ্রেশন যা ভেরিয়েবলগুলি ক্যাপচার করে না তা একটিতে সংকলিত হয়েছিলstatic কল সাইটে পদ্ধতিতে । রোজলিন এই আচরণটি পরিবর্তন করেছিলেন। এখন, কোনও ল্যাম্বদা, যা ভেরিয়েবলগুলি ক্যাপচার করে বা না, প্রদর্শন শ্রেণিতে রূপান্তরিত হয়:

এই উদাহরণ দেওয়া:

public class C
{
    public void M()
    {
        var x = 5;
        Action<int> action = y => Console.WriteLine(y);
    }
}

নেটিভ সংকলক আউটপুট:

public class C
{
    [CompilerGenerated]
    private static Action<int> CS$<>9__CachedAnonymousMethodDelegate1;
    public void M()
    {
        if (C.CS$<>9__CachedAnonymousMethodDelegate1 == null)
        {
            C.CS$<>9__CachedAnonymousMethodDelegate1 = new Action<int>(C.<M>b__0);
        }
        Action<int> arg_1D_0 = C.CS$<>9__CachedAnonymousMethodDelegate1;
    }
    [CompilerGenerated]
    private static void <M>b__0(int y)
    {
        Console.WriteLine(y);
    }
}

Roslyn:

public class C
{
    [CompilerGenerated]
    private sealed class <>c__DisplayClass0
    {
        public static readonly C.<>c__DisplayClass0 CS$<>9__inst;
        public static Action<int> CS$<>9__CachedAnonymousMethodDelegate2;
        static <>c__DisplayClass0()
        {
            // Note: this type is marked as 'beforefieldinit'.
            C.<>c__DisplayClass0.CS$<>9__inst = new C.<>c__DisplayClass0();
        }
        internal void <M>b__1(int y)
        {
            Console.WriteLine(y);
        }
    }
    public void M()
    {
        Action<int> arg_22_0;
        if (arg_22_0 = C.
                       <>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 == null)
        {
            C.<>c__DisplayClass0.CS$<>9__CachedAnonymousMethodDelegate2 =
          new Action<int>(C.<>c__DisplayClass0.CS$<>9__inst.<M>b__1);
        }
    }
}

রোজলিনে এই পরিবর্তনটি কেন করা হয়েছে সে সম্পর্কে ডেলিগেট ক্যাচিং আচরণের পরিবর্তনগুলি


2
ধন্যবাদ, আমি ভাবছিলাম যে আমার ফানক <int> f = () => 5 এর পদ্ধতি স্থির ছিল না কেন
ভিসি 74

2

1

পদ্ধতিটির কোনও বন্ধ নেই এবং এটি একটি স্ট্যাটিক পদ্ধতি নিজেই উল্লেখ করে (কনসোল.ব্রাইটলাইন), সুতরাং আমি এটি স্থিতিশীল হওয়ার আশা করব। পদ্ধতিটি বন্ধের জন্য একটি বেনামে অনামী প্রকার ঘোষণা করবে, তবে এই ক্ষেত্রে এটি প্রয়োজন হয় না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.