ডেলিগেট কী? [বন্ধ]


152

আমি বিভ্রান্ত যে একটি প্রতিনিধি এর আসল ভূমিকা কি?

আমার সাক্ষাত্কারগুলিতে আমাকে এই প্রশ্নটি বহুবার জিজ্ঞাসা করা হয়েছিল, তবে আমি মনে করি না যে সাক্ষাত্কারকারীরা আমার উত্তর নিয়ে সন্তুষ্ট ছিলেন।

ব্যবহারিক উদাহরণ দিয়ে কেউ কি আমাকে একটি বাক্যে সেরা সংজ্ঞা বলতে পারে?


21
কৌতূহলবশত, আপনি কী প্রতিক্রিয়া জানিয়েছিলেন যাতে আপনি কীভাবে এটি সংশোধন করতে পারবেন তা আমরা আপনাকে বলতে পারি?
অ্যান্টনি ফোরলনি

6
আমি আকর্ষণীয় মনে করি যে এই প্রশ্নটি বন্ধ ছিল তবে এতে 126 টি উর্ধ্বতন রয়েছে এবং 65 জন এটি পছন্দ হিসাবে চিহ্নিত করেছে। দেখে মনে হচ্ছে এটি খুব বিস্তৃত হলেও এটি এখনও খুব ভাল প্রশ্ন।
ধনী

উত্তর:


171

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

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

এখানেসি # এর জন্য একটি রেফারেন্স আপনি দেখতে পারেন:

সি # তে উদাহরণস্বরূপ, ধরা যাক যে আমরা করতে চেয়েছিলাম আমাদের একটি গণনা ছিল এবং আমরা একটি আলাদা গণনা পদ্ধতি ব্যবহার করতে চেয়েছিলাম যা রানটাইম অবধি আমরা জানি না। সুতরাং আমাদের কাছে এরকম কয়েকটি গণনার পদ্ধতি থাকতে পারে:

public static double CalcTotalMethod1(double amt)
{
    return amt * .014;
}

public static double CalcTotalMethod2(double amt)
{
    return amt * .056 + 42.43;
}

আমরা এইভাবে কোনও প্রতিনিধি স্বাক্ষর ঘোষণা করতে পারি:

public delegate double calcTotalDelegate(double amt);

এবং তারপরে আমরা এমন একটি পদ্ধতি ঘোষণা করতে পারি যা প্রতিনিধিটিকে এই জাতীয় প্যারামিটার হিসাবে গ্রহণ করে:

public static double CalcMyTotal(double amt, calcTotalDelegate calcTotal)
{
    return calcTotal(amt);
}

এবং আমরা CalcMyTotalযে ডেলিগেট পদ্ধতিটি ব্যবহার করতে চাইছিলাম তাতে পাস করার পদ্ধতিটিকে কল করতে পারি।

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);

19
সি-তে সহজ তবে কার্যকর ফাংশন পয়েন্টারটি করার জন্য +1
আইডেন বেল

3
আপনার উত্তর সম্পর্কিত একটি প্রশ্ন। সাধারণ উপায়ে কোনও ফাংশন কল করা থেকে এটি কীভাবে আলাদা? শুধু এই কারণেই এটি রানটাইমের সময় জানা যায় না?
নাভেদ

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

এটি রানটাইমের সময় জানা যায় না এবং এটি একটি ফাংশনের পরিবর্তে একটি সীমাবদ্ধ ফাংশন - Fooকোনও প্রতিনিধিকে একটি স্থিতিশীল পদ্ধতি বরাদ্দ this.Foo()করা কোনও ফাংশন পয়েন্টার হিসাবে স্থির ফাংশন না দিয়ে কল করবে (সিতে, আপনার প্রায়শই অতিরিক্ত void*প্যারামিটার থাকে thisফাংশন পয়েন্টারে পাস করুন )
পিট কির্খাম

1
সি / সি ++ এ ফাংশন পয়েন্টারগুলির সাথে সাদৃশ্য স্থাপনের জন্য দ্রুত এবং কার্যকর উদাহরণের জন্য +1। অনেক প্রশংসিত!
জি 21

19

একটি প্রতিনিধি সহজভাবে একটি ফাংশন পয়েন্টার হয়।
আপনার প্রতিনিধিটি চালানোর জন্য আপনি যে পদ্ধতিটি চান তা কেবল আপনাকে নির্ধারণ করুন। তারপরে কোডে আপনি ইনভোকের মাধ্যমে সেই পদ্ধতিটি কল করতে পারেন।

কিছু কোড প্রদর্শনের জন্য (এটি মেমরি থেকে লিখেছেন যাতে সিনট্যাক্স বন্ধ হতে পারে)

delegate void delMyDelegate(object o);

private void MethodToExecute1(object o)
{
    // do something with object
}

private void MethodToExecute2(object o)
{
    // do something else with object
}

private void DoSomethingToList(delMyDelegate methodToRun)
{
    foreach(object o in myList)
        methodToRun.Invoke(o);
}

public void ApplyMethodsToList()
{
    DoSomethingToList(MethodToExecute1);
    DoSomethingToList(MethodToExecute2);
}

16

এখান থেকে নেওয়া হয়েছে

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

বা, একটি সহজ ছদ্ম উদাহরণ হিসাবে: কিছু বস্তু 1 একটি অনুরোধ প্রেরণ করে। অবজেক্ট 1 তারপরে অনুরোধটি প্রেরণ করে এবং নিজেই অবজেক্ট 2 - ডেলিগেটে। অবজেক্ট 2 অনুরোধটি প্রক্রিয়া করে এবং কিছু কাজ করে। (দ্রষ্টব্য: উপরের লিঙ্কটি ভাল উদাহরণ দেয়)


উপরের লিঙ্কে প্রদত্ত উদাহরণ সঠিকভাবে প্রতিনিধিদলের বিবরণ দেয় না।
Hardik9850


4

একটি প্রতিনিধি একটি অবজেক্ট যা কোনও পদ্ধতির উল্লেখ করতে পারে। এইভাবে, যখন আমরা একটি প্রতিনিধি তৈরি করি, আমরা এমন একটি অবজেক্ট তৈরি করি যা কোনও পদ্ধতির রেফারেন্স ধরে রাখতে পারে। তদতিরিক্ত, পদ্ধতিটি এই রেফারেন্সের মাধ্যমে কল করা যেতে পারে। সুতরাং, একটি প্রতিনিধি পদ্ধতিটি নির্দেশ করে যা এটি নির্দেশ করে। প্রতিনিধিটির প্রধান সুবিধাটি হ'ল এটি আমাদের একটি পদ্ধতিতে কল নির্দিষ্ট করার অনুমতি দেয় তবে প্রকৃতপক্ষে পদ্ধতিটি সংকলনের সময় নয়, রানটাইমে নির্ধারিত হয়।

সরল প্রতিনিধি

Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)

http://knowpacific.wordpress.com/2012/01/26/delegate/


2

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

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

Delegates are like C++ function pointers but are type safe.
Delegates allow methods to be passed as parameters.
Delegates can be used to define callback methods.
Delegates can be chained together; for example, multiple methods can be called on a single event.
Methods do not have to match the delegate signature exactly.

সর্বজনীন প্রতিনিধি প্রকারের_পরে_ডিলেগেট প্রতিনিধি_নাম () // ঘোষণা

You can use delegates without parameters or with parameter list
If you are referring to the method with some data type then the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer. Here I am giving an example with String.

নিম্নলিখিত উদাহরণটি একটি প্রতিনিধি অপারেশন দেখায়:

    namespace MyDelegate
    {
        class Program
        {
            private delegate void Show(string s);


            // Create a method for a delegate.
            public static void MyDelegateMethod(string me

ssage)
        {
            System.Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            Show p = MyDelegateMethod;
            p("My Delegate");
            p.Invoke("My Delegate");
            System.Console.ReadLine();
        }
    }
}

মাল্টিকাস্ট ডেলিগেট কী?

এটি একটি প্রতিনিধি যা একাধিক পদ্ধতির রেফারেন্স ধারণ করে। মাল্টিক্যাস্ট প্রতিনিধিদের অবশ্যই কেবল এমন পদ্ধতি থাকতে হবে যা বাতিল হয়ে যায়, অন্যথায় রান-টাইম ব্যতিক্রম রয়েছে।

 delegate void MyMulticastDelegate(int i, string s);
 Class Class2
 {
  static void MyFirstDelegateMethod(int i, string s)
  {
    Console.WriteLine("My First Method");
  }

  static void MySecondDelegateMethod(int i, string s)
  {
    Console.WriteLine("My Second Method");
  }

  static void Main(string[] args)
  {
    MyMulticastDelegate Method= new MyMulticastDelegate(MyFirstDelegateMethod);
    Method+= new MyMulticastDelegate (MySecondDelegateMethod);
    Method(1,"Hi");             // Calling 2 Methodscalled
    Method-= new MyMulticastDelegate (MyFirstDelegateMethod);
    Method(2,"Hi");             //Only 2nd Method calling
  }
}

এখানে ডেলিগেটটি + = অপারেটর ব্যবহার করে যুক্ত করা হয় - এবং অপারেটর ব্যবহার করে অপসারণ করা হয়।

ডেলিগেট প্রকারগুলি .NET ফ্রেমওয়ার্কের প্রতিনিধি শ্রেণি থেকে প্রাপ্ত। প্রতিনিধি প্রকারগুলি সিল করা হয় — সেগুলি উত্পন্ন করা যায় না। যেহেতু তাত্ক্ষণিক প্রতিনিধি একটি অবজেক্ট, তাই এটি প্যারামিটার হিসাবে পাস করা যায়, বা কোনও সম্পত্তিতে বরাদ্দ করা যেতে পারে। এটি কোনও পদ্ধতির মাধ্যমে কোনও প্রতিনিধিটিকে প্যারামিটার হিসাবে গ্রহণ করতে এবং পরে ডেলিগেটকে কল করার অনুমতি দেয়। এটি একটি অ্যাসিক্রোনাস কলব্যাক হিসাবে পরিচিত।


1

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


1

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

বাটন 1. ক্লিক করুন + = নতুন সিস্টেম.এভেন্টহ্যান্ডলার (বোতাম 1_ক্লিক) সিস্টেম.এভেন্টহ্যান্ডলারটি এখানে প্রতিনিধি হিসাবে ঘোষিত হয়। নেট ইভেন্টগুলি ডেলিগেটের ধারণায় কাজ করে (বোতাম ক্লিকের মতো)

ডেলিগেটটি ব্যবহৃত হয় যখন আপনি জানেন না যে রান টাইমে কোন কোডটি প্রয়োগ করা উচিত তাই সেই সময় ডেলিগেট ইভেন্টগুলি পরিচালনা করতে ব্যবহৃত হয়

http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx


1

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


1

প্রতিনিধি হ'ল এমন একটি বস্তু যা কোনও ফাংশনের পয়েন্টার উপস্থাপন করে। তবে এটি এতে কোনও সাধারণ ফাংশন পয়েন্টার নয়:

1) অবজেক্ট ওরিয়েন্টেড

2) সুরক্ষিত টাইপ, অর্থাত্ এটি কেবল কোনও পদ্ধতির দিকে নির্দেশ করতে পারে এবং আপনি যে কাঁচা মেমরি ঠিকানাটি এটি দেখিয়েছেন সেটি পড়তে পারবেন না

3) দৃ strongly়ভাবে টাইপ করা হয়। এটি কেবল সেই পদ্ধতিগুলিতে নির্দেশ করতে পারে যা তার স্বাক্ষরগুলির সাথে মেলে।

4) একই সাথে একাধিক পদ্ধতির নির্দেশ করতে পারে।


1

প্রতিনিধিরা প্রধানত ইভেন্টগুলির সাথে ব্যবহৃত হয়।

প্রয়োজন হ'ল:

আপনি যখন প্রোগ্রামটি চালাবেন তখন আপনি কোনও কোডের টুকরোগুলি কার্যকর করতে চান না। প্রোগ্রামটি চালানোর পরে আপনি যখনই কোনও ঘটনা ঘটে তখন সেই টুকরা কোডটি কার্যকর করতে চান।

উদাহরণ:

  1. কনসোল আবেদন - কোডটি কেবলমাত্র আপনি প্রোগ্রাম চালনার সময় কার্যকর করা যেতে পারে। (মূল পদ্ধতির ভিতরে লিখিত)
  2. উইন্ডোজ অ্যাপ্লিকেশন (ইউজার ইন্টারফেস প্রোগ্রামিং) - প্রোগ্রামটি চালানোর পরে বোতামটি ক্লিক করার সময় কোডটি কার্যকর করা যেতে পারে।

এটি তারা যা বলে, সংকলনের সময় কোন পদ্ধতিটি প্রার্থনা করবে তা আপনি জানেন না। আপনি এটি কেবল রানটাইমেই জানবেন যা বোতামটি ক্লিক করার সময়।

প্রতিনিধি ছাড়া কোনও ইউজার ইন্টারফেস প্রোগ্রামিং সম্ভব নয়। কারণ আপনি যখনই কোড ব্যবহার করছেন তখনই ব্যবহারকারী যখন এমন ইভেন্ট তৈরি করে যা বোতামে ক্লিক করছে, টেক্সটবক্সে টাইপ করছে, ড্রপডাউনলিস্ট আইটেম নির্বাচন করছে এবং এই জাতীয় ....


0

একটি প্রতিনিধি এমন একটি জিনিস যার কাছে একটি কার্য অর্পিত হয়। প্রতিনিধি দলের প্রাথমিক উদ্দেশ্য কোডটি ডিকুয়াল করা এবং আরও বেশি নমনীয়তা এবং পুনরায় ব্যবহারের অনুমতি দেওয়া।

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

সাধারণ উদাহরণ:

SomeInterface
{
   public void doSomething();
}


SomeImplementation implements SomeInterface
{
   public void doSomething()
   {
      System.err.println("Was it good for you?");
   }

}


SomeCaller
{
   public void doIt(SomeInterface someInterface)
   {
      someInterface.doSomething();
   }
}

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

SomeService
{
    SomeInterface someImplementation = ... // assign here
    SomeOtherInterface someOtherImplementation = ... // okay, let's add a second

    public void doSomeWork()
    {
         someImplementation.doSomething();
         someOtherImplementation.doSomethingElse();
    }
}

(এনবি: বাস্তবায়ন কীভাবে নির্ধারিত হয় তা এই থ্রেডের পরিধি ছাড়াই beyond নিয়ন্ত্রণ এবং নির্ভরতা ইনজেকশনটির সন্ধানের বিপরীতমুখী।)


-2

সত্যিকার অর্থে "ফাংশন পয়েন্টার" না হলেও কোনও প্রতিনিধি দেখতে এই পিএইচপি-র মতো গতিময় ভাষা হতে পারে:



$func = 'foo';
$func();

function foo() {
    print 'foo';
}

বা জাভাস্ক্রিপ্টে আপনি এর মতো কিছু করতে পারেন:


var func = function(){ alert('foo!'); }
func();


2
এটি প্রতিনিধি দলের উদাহরণ নয়। আপনার উদাহরণস্বরূপ, আপনি যাকে ভেরিয়েবল ফাংশন বলে যা ব্যবহার করছেন যা মূলত একটি ফাংশনটির জন্য একই নামযুক্ত স্ট্রিংয়ের জন্য দেখায় যা ভেরিয়েবল উল্লেখ করে। : পরিবর্তনশীল ফাংশন দেখতে php.net/manual/en/functions.variable-functions.php
পাতলা জলরঙে আঁকা ছবি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.