none
Are members of Singleton class static? RRS feed

  • Question

  • I have a "singleton class" that has the following local variable:

    ObservableCollection<Price> _data = new ObservableCollection<Price>();

    If I use:

    return new ObservableCollection<Price> _data.Where(.....);

    or if I say:

    ObservableCollection<Price> mySubset = new ObservableCollection<Price>();

    and then add few Price objects from _data to this new collection and return it.

    Q. Am I correct that in both the above cases, the caller, will get references to the elements of the original collection _data. I do implement INotify - so, changes to any element of _data will get transmitted to the subsets that the above two statements would return?

    Tuesday, October 17, 2017 4:13 AM

All replies

  • No, members of a singleton aren't static unless you explicitly mark them so. It is important to understand that a singleton class and a static class are 2 entirely different things.

    A static class has no instances. Any static fields are effectively stored in global memory and won't go away until the process terminates. When accessing the members of the static class you don't reference an instance but the type itself.

    A singleton has a single instance. If it has any fields then they are tied to that instance. That instance is stored in memory just like any other object you create. Any time you want to reference members of the class you still have to specify the instance (the only instance in this case). Unlike a static class you could create a new instance of the singleton during the life of an application. I really cannot think of why you would but it is technically possible. Since it is really no different than any other class (other than you're restricting creation to a single instance) it behaves like any other instance class.

    As for your code, yes callers would get references to elements in the original collection but since you're newing up a new collection instance then they wouldn't get the original collection. Since this is observable you will get mixed results with this type of implementation. If the Price class implements INotifyPropertyChanged and somebody modified one of its properties then the other "copies" would get notified since they are reference types and they all point to the same instance. However if you add/remove an item to/from the collection then none of the other collections would notice because they are copies. Given your snippet of code I see no benefit in creating new collections (especially for that where clause). Simply change the return type to IEnumerable<Price> for the method(s) and then return the original collection. This has the same effect since the caller cannot modify the original collection. If they want to stuff the results into another observable collection then they can but there is no reason why your could would do that automatically.

    public class Price : INotifyPropertyChanged
    {
       //Interface implementation with helper OnPropertyChanged method
    
       public decimal Value 
       {  
          get => _value;
          set
          {
             if (value != _value)
             {
                _value = value;
                OnPropertyChanged(nameof(Value));
             };
          }
       }
       
       private decimal _value;
    }
    
    public class MyData 
    {
       public IEnumerable<Price> GetAll ()
       {
          //Return the underlying collection but as enumerable,
          //note that if the collection changes this will blow
          //up if used in foreach
          return _items;
       }
    
       public void Add ( Price item )
       {
          _items.Add(item);
       }
       
       private readonly ObservableCollection<Price> _items = new ObservableCollection<Price>();
    }
    
    //Usage
    var data = new MyData();
    var price = new Price() { Value = 10 };
    data.Add(price);
    price.PropertyChanged += (o,e) => Console.WriteLine("Changed");
    
    //Get the list
    var items = data.GetAll();
    foreach (var item in items)
    {
       //Will trigger the change event because it is the same
       //object
       item.Value = 20;
    }
    
    


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, October 17, 2017 3:50 PM
    Moderator
  • Thanks for the reply. Isn't it an ObservableCollection that notifies Add/Remove objects and IEumerable does not.

    Tuesday, October 17, 2017 6:21 PM
  • Yes, ObservableCollection extends the existing Collection<T> type with the ability to be notified when items are added/removed from the collection. If you want to expose that functionality then you'd use ObservableCollection. Of course if you already have a field of type ObservableCollection then it would make more sense to promote it to the public get-only property. Users can modify the list and anyone listening would get notified.

    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, October 17, 2017 6:31 PM
    Moderator