Results 1 to 8 of 8

Thread: Delegates

  1. #1
    Join Date
    Sep 2016
    Posts
    14

    Delegates

    C#:
    I struggle to understand the concept of delegates in C#. My question is: why on earth would you even want to use a delegate? You can use methods and classes and they will work just fine, won't they?

    I understood the syntax of delegate, also how events relate to delegates (a comparison to properties/fields), also concerning lambdas that they are an equivalent of an anonymous delegate.

    Then again what's the point of a delegate? A rudimentary question. Could some of the good folks from this forum help and elaborate please?
    Last edited by goldeen; 11-10-2016 at 03:43 AM.

  2. #2
    Join Date
    Feb 2014
    Posts
    277
    I've been waiting for c# ppl to respond to your question, because I too have tried multiple ways to learn this concept.
    I get what they do, but to me it really confuses code especially as I see 2 different ways to declare and invoke delegates.
    But I also know that until I do 'get' delegates thoroughly then I will have no way to understand the way Nelson used linq in the mmo series.

    Nelson explains Delegates in a few different videos c# 103 as well as Nelson's corner. I've looked up videos on youtube as well as the microsoft site. I've even bought a book on c# for beginners and still there is some block in my head that needs to be sorted out - because I need to figure out the chain that starts with Polymorphic, generics, then moves on to Anonymous, Delegates, IEnumerable, then Linq.

  3. #3
    Join Date
    Sep 2016
    Posts
    14
    Well thank you for a reply. LOL Any reply is good. At least I know I'm on the same page as some other people who learn this stuff. Yeah, I watched C# 103. Nelson explains it well, as he always does, however no matter how one could explain it, I find the idea/concept to be tough to absorb and fully digest.

    OK, since there is only one reply, let me paste what I found online.

    Firstly before proceeding to the Delegates, I had to sort out a few other concepts and definitions, since Nelson used them when talking about Delegates and I was a bit confused:

    * Function. According to some research done online (this StackOverFlow discussion), I found that in C# a Function = a Method. I take it that a concept of a function is a broader one, yet in C# there are no other functions than methods.

    This is actually important. Every time people talk about Delegates online, they say functions. According to the above, these are methods and nothing else. Always! Right?

    * Signature. From MSDN: "The signature of a method consists of the name of the method and the type and kind (value, reference, or output) of each of its formal parameters, considered in the order left to right. The signature of a method specifically does not include the return type, nor does it include the params modifier that may be specified for the right-most parameter."
    (StackOverFlow discussion)

    * Overload. From csharpindepth.com. "Just as a reminder, overloading is what happens when you have two methods with the same name but different signatures. At compile time, the compiler works out which one it's going to call, based on the compile time types of the arguments and the target of the method call."
    (csharpindepth.com Article)

    * Encapsulation. From csharp-station.com. "In object-oriented programming, you create objects that have state and behavior. An object’s state is the data or information it contains. For example, if you have a BankAccount object, its state could be Amount and CustomerName. Behavior in an object is often represented by methods. For example, the BankAccount object’s behavior could be Credit, Debit, and GetAmount. This sounds like a nice definition of an object, and it is, but you must also consider how this object will be used."
    (csharp-station.com Tutorial)

    All the above concepts were used when explaining Delegates in the C# 103.

    Out of the above mentioned concepts, I'm not sure if I really fully understand the concept of Encapsulation. Let's say you have an object, which you define: you define its state and behaviour and you wrap that in curly braces. So is Encapsulation the idea of "closing" the state and behaviour of the object within the curly braces? Is that all?

    I remember Nelson giving examples and saying such and such thing would break the encapsulation... which I do not understand. How could you break Encapsulation? The program won't compile if you don't use the curly braces? Would someone please explain how it works?

    Regarding Overloads, I understand the concept, however I wonder why you need Overloads? If I want to use different parameters, couldn't I simply define a different method with a different name???

    As to Signatures, do only Methods have Signature? What about a Class? If I define it, let's say: "public Class Whatever {}", is it called a Signature as well?

    Also are the following considered to be the same Signatures or different:
    public static void DisplayData (string name, int age) {}
    public static void DisplayData (string data01, int data02) {}
    ??
    What about this one:
    public static string DisplayData (string whatever1, int whatever2) {}
    ??

    DELEGATES

    Now to the Delegates. I found this article to explain Delegates well.
    Understanding Delegates

    Fine. They provide 2 examples: a) a simple definition of a Delegate b) an actual usage of a Delegate.

    a) Simple Delegate Syntax

    Code:
    class Program
        {
            public static string MergeCustomerDetails(string firstName, string lastName)
            {
                return firstName + " " + lastName;
            }
    
            public delegate string MyDelegate(string input1, string input2);
    
            static void Main(string[] args)
            {
                var myDelegate = new MyDelegate(MergeCustomerDetails);
    
                var result = myDelegate("John", "Citizen");
            }
        }
    What I understand is crucial in this example is to have the same Signature of the Delegate as the Method it will point to. Yet in this example we could as well use a Method, without bothering with the Delegate at all.

    b) Actual Delegate usage

    So according to what this article says a Delegate is a way to pass a Method into another Method, so that this 2nd Method can execute it. (They say functions, but from what I stated at the beginning of my post: in C# a function = a method).

    So in the following example they use 3 methods and that's why they say they use a Delegate.

    Code:
    public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }
    
        class Program
        {
            static bool IsChild(Person p)
            {
                return p.Age <= 18;
            }
    
            static bool IsAdult(Person p)
            {
                return p.Age >= 18;
            }
    
            static bool IsSenior(Person p)
            {
                return p.Age >= 65;
            }
    
            public delegate bool FilterDelegate(Person p);
    
            static void DisplayPeople(string title, List<Person> people, FilterDelegate filter)
            {
                Console.WriteLine(title);
    
                foreach (Person p in people)
                {
                    // here is where we use the delegate 'filter' as it was a function
                    if (filter(p))
                    {
                        Console.WriteLine("{0}, {1} years old", p.Name, p.Age);
                    }
                }
                Console.Write("\n\n");
            }
    
            static void Main(string[] args)
            {
                //Create 4 Person objects
                Person p1 = new Person() { Name = "John", Age = 41 };
                Person p2 = new Person() { Name = "Jane", Age = 69 };
                Person p3 = new Person() { Name = "Jake", Age = 12 };
                Person p4 = new Person() { Name = "Jessie", Age = 25 };
    
                //Create a list of Person objects and fill it
                List<Person> people = new List<Person>() { p1, p2, p3, p4 };
    
                // the third argument of each call is the method we want to pass
                DisplayPeople("Children:", people, IsChild);
                DisplayPeople("Adults:", people, IsAdult);
                DisplayPeople("Seniors:", people, IsSenior);
    
                Console.Read();
            }
        }
    Well, the problem here is that I think that the original concept is poor logic. I mean I wouldn't put this problem the way they put it before using Delegates. Maybe it's just me...
    Last edited by goldeen; 11-13-2016 at 09:40 AM.

  4. #4
    Join Date
    Oct 2011
    Posts
    547
    I will try to add some small input regarding this.
    Till then, don't know if you seen, there is also the coverage done for delegates in the XNA complete course (if you have access to it). Maybe that could help.

  5. #5
    Join Date
    Sep 2016
    Posts
    14
    Thank you. I will take a look.

    In the meanwhile, I got a bit intrigued and I approached their 'fantastic' example (*sarcasm*) with the following code.

    I guess you might approach the logic in many ways, but what I really don't like about the original example is that they provide 3 methods, which are almost the same. Looks ugly if you ask me.

    Not to mention that I would actually invoke Display method only once, not 3 times, but I got lazy.

    So why not code it like this:

    Code:
    public class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
    
            public string IsChildAdultSenior()
            {
                if (Age < 18)
                    return "Children";
                else if (Age < 65)
                    return "Adults";
                else
                    return "Seniors";
            }
        }
    
        class Program
        {
            public static void Display(string paramAge, List<Person> people)
            {
                Console.WriteLine(paramAge);
    
                foreach (Person p in people)
                {
                    if (p.IsChildAdultSenior() == paramAge)
                    {
                        Console.WriteLine("{0}, {1} years old", p.Name, p.Age);
                    }
                }
                Console.Write("\n\n");
            }
    
    
            static void Main(string[] args)
            {
                Person p1 = new Person() { Name = "John", Age = 41 };
                Person p2 = new Person() { Name = "Jane", Age = 69 };
                Person p3 = new Person() { Name = "Jake", Age = 12 };
                Person p4 = new Person() { Name = "Jessie", Age = 25 };
    
                List<Person> people = new List<Person>() { p1, p2, p3, p4 };
    
                Display("Children", people);
                Display("Adults", people);
                Display("Seniors", people);
    
                Console.Read();
            }
        }
    Last edited by goldeen; 11-13-2016 at 10:04 AM.

  6. #6
    Join Date
    Oct 2011
    Posts
    547
    I don't know if this is actually a good example but here goes:

    // basic food rating
    Code:
    enum ContestType
    {
        Spicy, Steak, Meat
    }
    
    class SpicyContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
    class SteakContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
    class MeatContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
    class Food { }
    
    class Program
    {
        static void Main(string[] args)
        {
            Food myfood = new Food();
    
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Meat, myfood));
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Spicy, myfood));
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Steak, myfood));
    
            Console.WriteLine("Done");
            Console.ReadLine();
        }
    
        static string AnalizeFood(ContestType vs, Food submited)
        {
            string result = string.Empty;
            switch (vs)
            {
                case ContestType.Spicy: result = (new SpicyContest()).Note(submited); break;
                case ContestType.Steak: result = (new SteakContest()).Note(submited); break;
                case ContestType.Meat: result = (new MeatContest()).Note(submited); break;
            }
            return result;
        }
    }
    // adding another contest after some weeks

    Code:
    enum ContestType
    {
        Spicy, Steak, Meat, Fresh
    }
    
    class SpicyContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
    class SteakContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
    class MeatContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
    /// NEW LINE ADDED HERE [first round ~after 3 weeks]
    class FreshContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
    class Food { }
    
    class Program
    {
        static void Main(string[] args)
        {
            Food myfood = new Food();
    
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Meat, myfood));
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Spicy, myfood));
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Steak, myfood));
    
            /// NEW LINE ADDED HERE [first round ~after 3 weeks]
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Fresh, myfood));
    
            Console.WriteLine("Done");
            Console.ReadLine();
        }
    
        static string AnalizeFood(ContestType vs, Food submited)
        {
            string result = string.Empty;
            switch (vs)
            {
                case ContestType.Spicy: result = (new SpicyContest()).Note(submited); break;
                case ContestType.Steak: result = (new SteakContest()).Note(submited); break;
                case ContestType.Meat: result = (new MeatContest()).Note(submited); break;
    
                /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                case ContestType.Fresh: result = (new FreshContest()).Note(submited); break;
            }
            return result;
        }
    }

    // adding another contest after some months

    Code:
    enum ContestType
    {
        Spicy, Steak, Meat, Fresh, Sweet
    }
    
    class SpicyContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
    class SteakContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
    class MeatContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
    /// NEW LINE ADDED HERE [first round ~after 3 weeks]
    class FreshContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
    /// NEW LINE ADDED HERE [secound round ~after 3 months]
    class SweetContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
    class Food { }
    
    class Program
    {
        static void Main(string[] args)
        {
            Food myfood = new Food();
    
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Meat, myfood));
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Spicy, myfood));
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Steak, myfood));
    
            /// NEW LINE ADDED HERE [first round ~after 3 weeks]
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Fresh, myfood));
    
            /// NEW LINE ADDED HERE [secound round ~after 3 months]
            Console.WriteLine("result is: {0}", AnalizeFood(ContestType.Sweet, myfood));
    
            Console.WriteLine("Done");
            Console.ReadLine();
        }
    
        static string AnalizeFood(ContestType vs, Food submited)
        {
            string result = string.Empty;
            switch (vs)
            {
                case ContestType.Spicy: result = (new SpicyContest()).Note(submited); break;
                case ContestType.Steak: result = (new SteakContest()).Note(submited); break;
                case ContestType.Meat: result = (new MeatContest()).Note(submited); break;
    
                /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                case ContestType.Fresh: result = (new FreshContest()).Note(submited); break;
    
                /// NEW LINE ADDED HERE [secound round ~after 3 months]
                case ContestType.Sweet: result = (new SweetContest()).Note(submited); break;
            }
            return result;
        }
    }

    // some inaccesible class from a developer | a black box
    // 1. how would you add another contest type (example: Tasty) since the class Analize is inacesible?

    Code:
        enum ContestType
        {
            Spicy, Steak, Meat, Fresh, Sweet
        }
    
        class SpicyContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
        class SteakContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
        class MeatContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
        /// NEW LINE ADDED HERE [first round ~after 3 weeks]
        class FreshContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
        
        /// NEW LINE ADDED HERE [secound round ~after 3 months]
        class SweetContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
        class Food { }
    
        class Program
        {
            static void Main(string[] args)
            {
                Food myfood = new Food();
    
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Meat, myfood));
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Spicy, myfood));
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Steak, myfood));
    
                /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Fresh, myfood));
    
                /// NEW LINE ADDED HERE [secound round ~after 3 months]
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Sweet, myfood));
    
                Console.WriteLine("Done");
                Console.ReadLine();
            }
            
        }
    
        class Analize
        {
            public static string Do(ContestType vs, Food submited)
            {
                string result = string.Empty;
                switch (vs)
                {
                    case ContestType.Spicy: result = (new SpicyContest()).Note(submited); break;
                    case ContestType.Steak: result = (new SteakContest()).Note(submited); break;
                    case ContestType.Meat: result = (new MeatContest()).Note(submited); break;
    
                    /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                    case ContestType.Fresh: result = (new FreshContest()).Note(submited); break;
    
                    /// NEW LINE ADDED HERE [secound round ~after 3 months]
                    case ContestType.Sweet: result = (new SweetContest()).Note(submited); break;
                }
                return result;
            }
        }

  7. #7
    Join Date
    Oct 2011
    Posts
    547
    Please, take a peak only after you found a solution for the code in the previous post (the question in red)

    Code:
    enum ContestType
        {
            Spicy, Steak, Meat, Fresh, Sweet
        }
    
        interface IContest{ string Note(Food food); }
    
        class SpicyContest : IContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
        class SteakContest : IContest { public string Note(Food food) { return this.GetType().Name; } /*return a analysis*/ }
        class MeatContest : IContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
        /// NEW LINE ADDED HERE [first round ~after 3 weeks]
        class FreshContest : IContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
        
        /// NEW LINE ADDED HERE [secound round ~after 3 months]
        class SweetContest : IContest { public string Note(Food food) { return this.GetType().Name; } /*return an analysis*/ }
    
        class Food { }
    
        class Program
        {
            static void Main(string[] args)
            {
                Food myfood = new Food();
    
                Console.WriteLine("{0}{1} Analize {0}", Environment.NewLine, "\t");
    
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Meat, myfood));
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Spicy, myfood));
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Steak, myfood));
    
                /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Fresh, myfood));
    
                /// NEW LINE ADDED HERE [secound round ~after 3 months]
                Console.WriteLine("result is: {0}", Analize.Do(ContestType.Sweet, myfood));
    
    
                ////////////////////////////////////////////
                // By interface
    
                Console.WriteLine("{0}{1} BetterAnalizeByInterface {0}", Environment.NewLine, "\t");
    
                Console.WriteLine("result is: {0}", BetterAnalizeByInterface.Do((new MeatContest()), myfood));
                Console.WriteLine("result is: {0}", BetterAnalizeByInterface.Do((new SpicyContest()), myfood));
                Console.WriteLine("result is: {0}", BetterAnalizeByInterface.Do((new SteakContest()), myfood));
    
                /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                Console.WriteLine("result is: {0}", BetterAnalizeByInterface.Do((new FreshContest()), myfood));
    
                /// NEW LINE ADDED HERE [secound round ~after 3 months]
                Console.WriteLine("result is: {0}", BetterAnalizeByInterface.Do((new SweetContest()), myfood));
    
                ////////////////////////////////////////////
                // By delegate
    
                Console.WriteLine("{0}{1} BetterAnalizeByDelegate {0}", Environment.NewLine, "\t");
    
                Console.WriteLine("result is: {0}", BetterAnalizeByDelegate.Do(new ContestDelegate((new MeatContest()).Note), myfood));
                Console.WriteLine("result is: {0}", BetterAnalizeByDelegate.Do(new ContestDelegate((new SpicyContest()).Note), myfood));
                Console.WriteLine("result is: {0}", BetterAnalizeByDelegate.Do(new ContestDelegate((new SteakContest()).Note), myfood));
    
                /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                Console.WriteLine("result is: {0}", BetterAnalizeByDelegate.Do(new ContestDelegate((new FreshContest()).Note), myfood));
    
                /// NEW LINE ADDED HERE [secound round ~after 3 months]
                Console.WriteLine("result is: {0}", BetterAnalizeByDelegate.Do(new ContestDelegate((new SweetContest()).Note), myfood));
                
                Console.WriteLine("Done");
                Console.ReadLine();
            }
            
        }
    
        class BetterAnalizeByInterface
        {
            public static string Do(IContest contest, Food submited)
            {
                // do some stuff here before calling the note
    
                return contest.Note(submited);
            }
        }
    
    
        delegate string ContestDelegate(Food submited);
        class BetterAnalizeByDelegate // some better example could probably be used here
        {
            public static string Do(ContestDelegate delegated, Food submited)
            {
                // do some stuff here before calling the note
    
                return delegated(submited);
            }
        }
    
        // some inaccesible class from a developer | a black box
        // 1. how would you add another contest type (example: Tasty) since the class is inacesible?
        class Analize
        {
            public static string Do(ContestType vs, Food submited)
            {
                string result = string.Empty;
                switch (vs)
                {
                    case ContestType.Spicy: result = (new SpicyContest()).Note(submited); break;
                    case ContestType.Steak: result = (new SteakContest()).Note(submited); break;
                    case ContestType.Meat: result = (new MeatContest()).Note(submited); break;
    
                    /// NEW LINE ADDED HERE [first round ~after 3 weeks]
                    case ContestType.Fresh: result = (new FreshContest()).Note(submited); break;
    
                    /// NEW LINE ADDED HERE [secound round ~after 3 months]
                    case ContestType.Sweet: result = (new SweetContest()).Note(submited); break;
                }
                return result;
            }
        }
    Hope this helps in a small bit. Please contribute, ask or correct me if needed.

  8. #8
    Join Date
    Aug 2010
    Posts
    158
    Delegates in programming are just like delegates in real life. A delegate is just a person that represent you somewhere that you can not be. You are delegating your responsibility to someone else in your place. If you hard coded the person to represent you then it would not work in all cases. What if that person was sick?

    Delegates are also the base for Events, Actions, and Funcs. They are all just abstracting away the annoying parts of the delegate structure.

    So delegates are more than just adding new functionality to something you own. In many cases they are used to add functionality at a higher level then a developer has access too. Imagine that you are developing a framework for something and other developers will use this framework to build their programs on top of. If the underlying framework needs to call a method in the higher level framework it would use a delegate to do that. The framework programmer would provide a delegate signature that would need to be used and would call what ever methods are attached to that delegate.

    In Deferred frameworks you might see everything being wrapped into callbacks. A call back is just another name for a delegate. After you have done something. Execute this callback. You can also create trees of deferred logic that will execute multiple layers. Consider the following block of code. We are creating a large chain of delegates that will execute an order we decide. It won't run anything until the SetResult line that starts its execution. I could potentially pass that A object to another class and have it execute it. It doesn't have to be bound to a single class that the methods reside in.

    Code:
    Deferred A = new Deferred();
    A
        .OnAlways(() => Console.WriteLine("A.OnAlways"))
        .OnFail(() => Console.WriteLine("A.OnFail"))
        .OnSuccess(() => Console.WriteLine("A.OnSuccess"));
    
    A.Then(() =>
        {
            Console.WriteLine("A.Then1");
            return Deferred.Success();
        })
        .Then(() =>
        {
            Console.WriteLine("A.Then2");
            return Deferred.Success();
        })
        .Then(() =>
        {
            Console.WriteLine("A.Then3");
            return Deferred.Success();
        })
        .Then(() =>
        {
            Console.WriteLine("A.Then4");
            return Deferred.Success();
        });
    
    A.SetResult(true, null);
    Some frameworks like NodeJS are using an execution style like this so that it can queue up thins to be processed at the end of a cycle instead of linearly.

  9. #9
    Join Date
    Mar 2017
    Posts
    0

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •