একটি ভেরিয়েবলের জন্য কোড নির্ধারণ করা


124

কোনও ভেরিয়েবল তৈরি করা এবং এতে কোডের একটি লাইন বরাদ্দ করা কি সম্ভব:

ButtonClicked = (MessageBox.Show("Hello, World!"));

... সুতরাং যখন আমি ভেরিয়েবলটি ব্যবহার করব, এটি কোডের লাইনটি কার্যকর করবে।


100
কোডিংয়ে নতুন হওয়া এবং একটি ভাল প্রশ্ন জিজ্ঞাসা করার বিরল সংমিশ্রণের জন্য +1: আপনি কী করতে চান তা বুঝতে এবং এটি ভালভাবে ব্যাখ্যা করতে পারেন, আপনি কেবল এর জন্য শব্দটি জানেন না তাই আপনি নিজেরাই এটি খুঁজে পেতে পারেন না।
টিম এস

10
আপনি যে শব্দটির সন্ধান করছেন তা একটি প্রতিনিধি
লাসে ভি কার্লসেন

stackoverflow.com/questions/6187944/… এটি পরীক্ষা করে দেখুন, আমার মনে হয় আপনার যথেষ্ট পরিমাণ ব্যাখ্যার প্রয়োজন হবে। এএসপি প্রায় ক্ষেত্রে উইন্টারফোমের মতো কাজ করে।
সিশারপি

অবজেক্টিভ-সি-তে অনেকগুলি ব্লকের মতো শোনাচ্ছে
ব্রায়ান ট্রেসি

উত্তর:


89

আপনি এটির Actionমতো এটি নির্ধারণ করতে পারেন :

var ButtonClicked = new Action(() => MessageBox.Show("hi"));

তারপরে এটিকে কল করুন:

ButtonClicked();

সম্পূর্ণতার জন্য (বিভিন্ন মন্তব্যের ক্ষেত্রে) ...

এরিক যেমন বলেছেন, আপনি একাধিক কোডের লাইন সম্পাদন করতে পারেন:

var ButtonClicked = new Action(() =>
{
    MessageBox.Show("hi");

    MessageBox.Show("something else");  // something more useful than another popup ;)
});

টিম যেমন বলেছে, আপনি Actionকীওয়ার্ডটি বাদ দিতে পারেন

Action ButtonClicked = () => MessageBox.Show("hi");

Action ButtonClicked = () =>
{
    // multiple lines of code
};

খালি বন্ধনী সম্পর্কে, কেআরআইনের মন্তব্যটি সম্বোধন করার জন্য, আপনি অ্যাকশনে পাঠাতে সক্ষম হতে চান এমন পরামিতিগুলির তালিকার প্রতিনিধিত্ব করে (এই ক্ষেত্রে কিছুই নয়)

যদি উদাহরণস্বরূপ, আপনাকে দেখাতে হবে বার্তা নির্দিষ্ট করতে চান, তাহলে আপনি একটি প্যারামিটার হিসাবে "বার্তা" যোগ করতে পারিনি (নোট যে আমি পরিবর্তন Action করতে আদেশ একটি একক পংক্তি পরামিতি উল্লেখ করার মধ্যে) :Action<string>

Action<string> ButtonClicked = (message) => MessageBox.Show(message);

ButtonClicked("hello world!");

10
Action ButtonClicked = () => MessageBox.Show("hi");সমতুল্য এবং আইএমও সুন্দর (যদি আপনি চান তবে প্যারেনস যুক্ত করুন)
টিম এস

1
ক্রিয়াকলাপের কোডের একক লাইনের চেয়েও বেশি সমাধান করাও সম্ভব।
এরিক ফিলিপস

2
@ সিশারপি আমি নিশ্চিত নই যে এই ধারণাটি ওপেনের পক্ষে সহায়ক।
এরিক ফিলিপস

2
@ সিশারপি কেন ওপিকে এটি ব্যবহার করতে পারছে না WinForms?
ভিভাত

2
@ সিশারপি আমি দেখছি আপনি কী বলছেন। যদি সে আসলে কোনও Button.Clickইভেন্টের সাথে এটি সংযুক্ত করে এবং কোনও নাম পরিবর্তন করতে পারে তবে এটি কোনও ভেরিয়েবলে সংরক্ষণ করে না ButtonClicked
ভিভাত

51

আপনার ক্ষেত্রে, আপনি একটি ব্যবহার করতে চান delegate

আসুন দেখুন কীভাবে কোনও প্রতিনিধি কাজ করে এবং কীভাবে আমরা এর ধারণাটি বোঝার মাধ্যমে একটি সহজ ফর্মে পৌঁছাতে পারি:

// Create a normal function
void OnButtonClick()
{
    MessageBox.Show("Hello World!");
}
// Now we create a delegate called ButtonClick
delegate void ButtonClick();

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

এখন, আমাদের যা আছে তা ব্যবহার করি; আমরা প্রতিনিধিটিকে ঠিক যেমন অন্য কোনও চলক সংজ্ঞায়িত করব:

ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);

আমরা মূলত বাটনক্লিকড নামে একটি নতুন ভেরিয়েবল তৈরি করেছি, এর মধ্যে এক ধরণের বাটনক্লিক রয়েছে (যা একটি প্রতিনিধি) এবং যখন এটি ব্যবহার করা হবে, তখন এটি অন্বটনক্লিক () পদ্ধতিতে পদ্ধতিটি কার্যকর করবে।
এটি ব্যবহার করতে আমরা কেবল কল করি:ButtonClicked();

সুতরাং পুরো কোডটি হ'ল:

delegate void ButtonClick();

void OnButtonClick()
{
    MessageBox.Show("Hello World!");
}

void Foo()
{
    ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
    ButtonClicked(); // Execute the function.
}  

এখান থেকে, আমরা ল্যাম্বদা এক্সপ্রেশনগুলিতে চলে যেতে পারি এবং তারা দেখতে পাবে যে তারা আপনার পরিস্থিতিতে কীভাবে কার্যকর হতে পারে:
অনেকগুলি প্রতিনিধি ইতিমধ্যে .NET গ্রন্থাগার দ্বারা সংজ্ঞায়িত করা হয়েছে, যেমন অ্যাকশন জাতীয় কিছু রয়েছে, যা কোনও প্যারামিটার গ্রহণ করে না এবং কোনও মান দেয় না। এটিকে সংজ্ঞায়িত করা হয়েছে public delegate void Action();
আপনি প্রতিবার নতুন প্রতিনিধি সংজ্ঞার প্রয়োজনের পরিবর্তে আপনি সর্বদা এটি আপনার প্রয়োজনের জন্য ব্যবহার করতে পারেন। উদাহরণস্বরূপ পূর্ববর্তী প্রসঙ্গে আপনি সবে লিখতে পারতেন

Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();

যা একই কাজ করতে হবে।
আপনি যখন প্রতিনিধিদের কীভাবে ব্যবহার করবেন সে সম্পর্কে বিভিন্ন উপায়ে দেখেছেন, আসুন আমাদের প্রথম লাম্বদা এক্সপ্রেশনটি ব্যবহার করুন। লাম্বডা এক্সপ্রেশনগুলি বেনামে ফাংশন; সুতরাং, এগুলি সাধারণ ফাংশন তবে নাম ছাড়া। সেগুলি এই ফর্মগুলির মধ্যে:

x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("I do not have parameters!");

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

Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );

বা আরও সহজ,

Action ButtonClicked = () => MessageBox.Show("Hello World!");

তারপরে কেবল কল ButtonClicked();করুন অবশ্যই আপনার বহু কোডের কোডও থাকতে পারে তবে আমি আপনাকে আরও বিভ্রান্ত করতে চাই না। এটি যদিও এর মতো দেখাবে:

Action ButtonClicked = () => 
{
    MessageBox.Show("Hello World!");
};
ButtonClicked();

আপনি চারপাশে খেলতেও পারেন, উদাহরণস্বরূপ, আপনি এই জাতীয় কোনও ক্রিয়াকলাপ চালাতে পারেন:

new Action(() => MessageBox.Show("Hello World!"))();

দীর্ঘ পোস্টের জন্য দুঃখিত, আশা করি এটি খুব বিভ্রান্তিকর হয়নি :)

সম্পাদনা: আমি উল্লেখ করতে ভুলে গেছি যে একটি বিকল্প ফর্ম যা প্রায়শই ব্যবহৃত না হলেও ল্যাম্বডা অভিব্যক্তিগুলি বুঝতে সহজ করে তুলতে পারে:

new Action(delegate() {
    Console.WriteLine("I am parameterless");
})();

জেনেরিকগুলি ব্যবহার করে:

// Defines a delegate that has one parameter of type string. You could pass as many parameters as you want.
new Action<string>(delegate(string x) {
    Console.WriteLine(x);
})("I am a string parameter!");

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

new Action<string>(x => {
    Console.WriteLine(x);
})("I am a string parameter!");

বা:

new Action<string>(x => Console.WriteLine(x))("I am a string parameter!");

EDIT2: এর
Action<string>প্রতিনিধিত্ব public void delegate Action(string obj);
Action<string,string>হ'ল public void delegate Action(string obj, string obj2);
সাধারণভাবে Action<T>একটি প্রতিনিধিত্ব, এর প্রতিনিধিত্বpublic void delegate Action<T>(T obj);

সম্পাদনা 3: আমি জানি পোস্টটি এখানে কিছুক্ষণ ছিল, তবে আমি মনে করি এটি উল্লেখ করা সত্যিই দুর্দান্ত: আপনি এটি করতে পারেন, যা বেশিরভাগই আপনার প্রশ্নের সাথে সম্পর্কিত:

dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show;
aFunction("Hello, world!");

বা সহজভাবে:

Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");

7

Lazyবর্গ বিশেষভাবে পারে এমন একটি মান নির্ণিত হবে না যতক্ষণ না আপনি এটা জন্য অনুরোধ প্রতিনিধিত্ব করতে ডিজাইন করা হয়েছে। আপনি এটি এমন একটি পদ্ধতি সরবরাহ করে নির্মাণ করেন যা এটি কীভাবে তৈরি করা উচিত তা নির্ধারণ করে তবে এটি সেই পদ্ধতিটি একাধিকবার পরিচালিত করবে না (এমনকি মানটির অনুরোধ করে একাধিক থ্রেডের মুখেও) এবং কেবলমাত্র অতিরিক্ত অতিরিক্ত অনুরোধের জন্য ইতিমধ্যে নির্মিত মানটি ফিরিয়ে দিবে:

var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));

var result = foo.Value;

মনে রাখবেন যে Lazyপ্রচুর পরিমাণে প্রক্রিয়াকরণ শক্তি প্রয়োজন এমন মানগুলির জন্য ব্যবহার করা উচিত এবং আপনার সেগুলি ইন্টারঅ্যাকশন করার জন্য ব্যবহার করা উচিত নয় (কারণ এর অর্থশাস্ত্রটি .Valueহ'ল এটি কোনও সম্পত্তি হিসাবে অনুরূপ কোনও মূল্য ফেরত দেয়, কোনও (ইন্টারেক্টিভ) ক্রিয়া নয়)। পরিবর্তে এই জাতীয় ক্রিয়াকলাপের জন্য একটি প্রতিনিধি ব্যবহার করা উচিত।
হাবিল

1
@ আবেল না, এটি এমন মানের জন্য নয় যেগুলির জন্য প্রচুর পরিমাণে প্রক্রিয়াকরণ শক্তি প্রয়োজন, এটি এমন কোনও মানের জন্য যা আপনি যখন না জিজ্ঞাসা না করা পর্যন্ত এটি আরম্ভ করতে চান, তবে কখনও কখনও এই মানটিকে একবারের বেশি আরম্ভ না করে। মান এখানে Value হয় ব্যবহৃত; এটি DialogResultবার্তা বাক্সটি দেখানো থেকে প্রাপ্ত। এই সমাধান এবং একটি প্রতিনিধি ব্যবহারের মধ্যে প্রাথমিক পার্থক্য হ'ল প্রতিবার অনুরোধ করা হয় বা না হলে মানটি পুনরায় গণনা করা উচিত। প্রয়োজনীয়তার বিষয়ে আমার ব্যাখ্যাটি হ'ল এটি ধারণাগতভাবে কোনও মানকে আরম্ভ করছে, পুনরাবৃত্তি করার জন্য কোনও অপারেশন নয় ।
পরিবেশন করুন

Lazyসহজেই ভুলভাবে ব্যবহার করা যায়। এর নিজের ওভারহেড রয়েছে, একটি "ছোট" টাস্ক পিছনে "ন্যায়বিচার" ব্যবহার করা এটি লাভের চেয়ে বেশি ওভারহেড আহ্বান করবে। কোনও সম্পত্তি থেকে মেসেজবাক্সগুলি দেখানো (ইমো) সাধারণভাবে খারাপ অভ্যাস, নির্বিশেষে Lazy। বিএসডব্লিউ, এমএসডিএন থেকে, আমি উদ্ধৃতি দিয়েছি: "একটি বৃহত বা সংস্থান-নিবিড় বস্তুর সৃষ্টি স্থগিত করার জন্য অলস সূচনা ব্যবহার করুন" । আপনি এর সাথে একমত হতে পারেন না, তবে এটি মূলত এটির জন্য ডিজাইন করা হয়েছিল।
হাবিল

1
@ আবেল এর Lazyমতো একটি প্রেক্ষাপটে অভিনয়ের জন্য ওভারহেড অবশ্যই অবহেলিত ; এটি কোনও বার্তা বাক্সে ক্লিক করার জন্য মানুষের অপেক্ষা করার সময়টির তুলনায় ফিকে হয়ে যাবে। এটি বেশিরভাগ অন্তর্নিহিত অ্যাপ্লিকেশনটির আসল প্রয়োজনীয়তার সাথে নেমে আসে; প্রশ্নের অস্পষ্টতা একটি উদ্দেশ্যমূলক সঠিক উত্তরটিকে অসম্ভব করে তোলে। এটি প্রশ্নের একটি ব্যাখ্যা। হিসাবে সম্পত্তি সম্পত্তি খুব খারাপ কাজ অনেক কাজ করছেন; দৃশ্যত আপনি মৌলিকভাবে সমগ্র নকশা বিরোধিতা করছি Lazy। আপনি যে মতামত স্বাগত জানাই।
17

দুঃখিত, আপনি নিশ্চয়ই আমাকে ভুল বুঝে গেছেন। অবশ্যই, MessageBox ওভারহেড সহ नगणনীয় (আমি কেবল কোনও সম্পত্তির ভিতরে ইউআই ব্যবহার করব না)। আমি সাধারণভাবে ছোট কার্যগুলি বোঝাতে চেয়েছিলাম (পিছিয়ে দেওয়ার মতো 2 + 3 * 4 / i), যেখানে ক্লোজার তৈরির ওভারহেড গণনার চেয়ে বেশি। এবং আমি মনে করি আমি পুরোপুরি আলিঙ্গন করেছি Lazy, বাস্তবে আমরা এটিকে এফ # তে খুব বেশি ব্যবহার করি (সি # তে কিছুটা কম) এবং আমরা আপনাকে যেভাবে কঠোরভাবে যত্নবান হতে হবে তা শিখতে পেরেছি, esp। কর্মক্ষমতা সম্মানের সাথে।
আবেল

4

আমি আপনার প্রশ্নটি যেভাবে পড়ছি, এটি কি জিইউআই নিয়ন্ত্রণের প্রসঙ্গে?

যদি এটি ডাব্লুপিএফ হয় তবে নিয়ন্ত্রণগুলি থেকে আদেশগুলি হ্যান্ডেল করার "ডান" উপায়টি দেখুন: http://msdn.microsoft.com/en-us/library/ms752308(v=vs.110).aspx

... তবে এটি একটি ব্যথা এবং ওভারকিল হতে পারে। একটি সাধারণ সাধারণ ক্ষেত্রে, আপনি কোনও ইভেন্ট হ্যান্ডলার খুঁজছেন, যেমন:

myButton.Click += (o, e) => MessageBox.Show("Hello, World!");

ইভেন্ট ইভেন্ট হ্যান্ডলারটি বিভিন্ন উপায়ে পরিচালনা করা যায়। উপরের উদাহরণটি বেনামে ফাংশন ব্যবহার করে তবে আপনি এটি করতেও পারেন:

Action<object, RoutedEventArgs> sayHello = (o, e) => MessageBox.Show("Hello, World");
myButton.Click += new RoutedEventHandler(sayHello);

... ঠিক যেমন আপনি ভেরিয়েবল হিসাবে নির্ধারিত কোনও ফাংশন (বা এখানে "অ্যাকশন" দিয়ে) জিজ্ঞাসা করেছিলেন।


1

আপনি চলক সময়ে সি # কোড বরাদ্দ করতে পারবেন, রানটাইম সময়ে সংকলন করে কোডটি চালাবেন:

  • আপনার কোড লিখুন:

    // Assign C# code to the code variable.
    string code = @"
    using System;
    
    namespace First
    {
        public class Program
        {
            public static void Main()
            {
                " +
                "Console.WriteLine(\"Hello, world!\");"
                + @"
            }
        }
    }
    ";
  • সংকলকটির সরবরাহকারী এবং পরামিতিগুলি তৈরি করুন:

    CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerParameters parameters = new CompilerParameters();
  • সংকলকটির পরামিতিগুলি নির্ধারণ করুন:

    // Reference to System.Drawing library
    parameters.ReferencedAssemblies.Add("System.Drawing.dll");
    // True - memory generation, false - external file generation
    parameters.GenerateInMemory = true;
    // True - exe file generation, false - dll file generation
    parameters.GenerateExecutable = true;
  • সমাবেশ সংগ্রহ করুন:

    CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
  • ত্রুটিগুলি পরীক্ষা করুন:

    if (results.Errors.HasErrors)
    {
            StringBuilder sb = new StringBuilder();
    
            foreach (CompilerError error in results.Errors)
            {
                    sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
            }
    
            throw new InvalidOperationException(sb.ToString());
    }
  • সমাবেশ, টাইপ এবং প্রধান পদ্ধতি পান:

    Assembly assembly = results.CompiledAssembly;
    Type program = assembly.GetType("First.Program");
    MethodInfo main = program.GetMethod("Main");
  • চালাও এটা:

    main.Invoke(null, null);

রেফারেন্স:

http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime


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