Search code examples
c#eventssender

get publisher class field from sender


I want to get my field >>> NumberOfElementsInMyList from sender, How Can I do it? I couldn't find this kind of question here (what I have seen, was about windows forms), so ...

class Program
{
    static void Main(string[] args)
    {
        Publisher PublisherObject = new Publisher();
        PublisherObject.NumberAdded += PublisherObject_NumberAdded;

        PublisherObject.AddNumber(int.Parse(Console.ReadLine());
    }

    static void PublisherObject_NumberAdded(object sender, EventArgs e)
    {
        //I want to write on the console  "NumberOfElementsInMylist"

        //I tried: 

        //sender.NumberOfElementsInMylist -- not works
        //Publisher obj=(publisher)sender   and then sender.NumberOfElementsInMylist
        //not works
        Console.WriteLine("number of elements in list is ---> "+ ???? );
    }
}

class Publisher
{
    public event EventHandler NumberAdded;

    public int NumberOfElementsInMyList;

    List<int> MyList=new List<int>();

    public void AddNumber(int NumberToAdd)
    {
        MyList.Add(NumberToAdd);

        NumberOfElementsInMyList = MyList.Count;

        NumberAdded(this, new EventArgs());
    }
}

Solution

  • To literally answer your question, the reason why you can't access the NumberOfElementsInMyList field is because when you create the EventArgs, your instance of Publisher is being cast as an object (which you can do since all classes inherit from object.) So to see the properties (or field) of Publisher, you have to cast the sender as Publisher.

    var numberOfElements = ((Publisher)sender).NumberOfElementsInMyList;
    

    A downside to this is that hypothetically, sender might not be a Publisher. Because sender is an object, it could technically be anything.

    You can also create your own event handler delegate and event args instead of using the boilerplate EventHandler delegate.

    public delegate void NumberAdded(Publisher source, NumberAddedEventArgs eventArgs);
    
    public class NumberAddedEventArgs : EventArgs
    {
        public NumberAddedEventArgs(int numberAdded, numberOfItemsInList)
        {
            NumberAdded = numberAdded;
            NumberOfItemsInList = numberOfItemsInList;
        }
    
        public int NumberAdded { get; private set; }
        public int NumberOfItemsInList { get; private set; }
    }
    
    public class Publisher
    {
        public event EventHandler NumberAddedEvent;
    
        public int NumberOfElementsInMyList;
    
        List<int> MyList = new List<int>();
    
        public void AddNumber(int NumberToAdd)
        {
            MyList.Add(NumberToAdd);
    
            NumberOfElementsInMyList = MyList.Count;
    
            NumberAddedEvent?.Invoke(this, new NumberAddedEventArgs(NumberToAdd, 
                NumberOfElementsInMyList));
        }
    }
    
    var numberOfElementsInList = args.NumberOfItemsInList; // much better!
    

    The (object sender, EventArgs args) is a strange convention. In any other scenario we would create strongly-typed methods and delegates. But in this case there's a tendency to use something that's not strongly-typed because it's a convention.