Singleton类的成员是静态的吗? [英] Are members of Singleton class static?

查看:79
本文介绍了Singleton类的成员是静态的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个"单身类"具有以下局部变量:


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



如果我使用:


返回新的  ;&的ObservableCollection LT;价格> _data.Where(.....);


或者如果我说:


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


然后将几个Price对象从_data添加到此新集合并返回它。



Q.我是否正确,在上述两种情况下,调用者都将获得对原始集合_data元素的引用。我实现了INotify - 所以,对_data的任何元素的更改都将传递给上面两个语句
将返回的子集?

解决方案

< blockquote>

不,单例的成员不是静态的,除非你明确标记它们。重要的是要理解单例类和静态类是完全不同的两个东西。


静态类没有实例。任何静态字段都有效地存储在全局内存中,并且在进程终止之前不会消失。访问静态类的成员时,您不引用实例,而是引用类型本身。


单例具有单个实例。如果它有任何字段,那么它们与该实例绑定。该实例存储在内存中,就像您创建的任何其他对象一样。每当你想引用类的成员时,你仍然必须指定实例
(在这种情况下唯一的实例)。与静态类不同,您可以在应用程序的生命周期中创建单例的新实例。我真的想不起你为什么会这样,但技术上是可行的。因为它与任何其他
类没有什么不同(除了你将创建限制为单个实例),它的行为与任何其他实例类一样。


至于你的代码,是调用者将获得对原始集合中元素的引用,但由于您正在新建一个新的集合实例,因此他们无法获得原始集合。由于这是可观察的,因此您将使用此类型
的实现获得混合结果。如果Price类实现了INotifyPropertyChanged并且有人修改了它的一个属性,那么另一个"副本"被修改。会得到通知,因为它们是引用类型,并且它们都指向同一个实例。但是,如果你
在集合中添加/删除一个项目,那么其他任何集合都不会注意到,因为它们是副本。鉴于您的代码片段,我认为创建新集合没有任何好处(特别是对于where子句)。只需将退货类型更改为
IEnumerable< Price>对于方法然后返回原始集合。这具有相同的效果,因为调用者无法修改原始集合。如果他们想要将结果填充到另一个可观察的集合中,那么他们可以但是
并不是你能够自动完成的原因。

公共类价格:INotifyPropertyChanged 
{
//使用帮助器的接口实现OnPropertyChanged方法

公共小数值
{
get => _值;
设置
{
if(value!= _value)
{
_value = value;
OnPropertyChanged(nameof(Value));
};
}
}

private decimal _value;
}

公共类MyData
{
public IEnumerable< Price> GetAll()
{
//返回基础集合,但是可枚举,
//请注意,如果集合发生变化,如果在foreach $ b中使用,则会增加
// up $ b返回_items;
}

public void添加(价格商品)
{
_items.Add(item);
}

private readonly ObservableCollection< Price> _items = new ObservableCollection< Price>();
}

//用法
var data = new MyData();
var price = new Price(){Value = 10};
data.Add(price);
price.PropertyChanged + =(o,e)=> Console.WriteLine(QUOT;变更");

//获取清单
var items = data.GetAll();
foreach(项目中的var项目)
{
//将触发更改事件,因为它是相同的
//对象
item.Value = 20;
}


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?

解决方案

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;
}


这篇关于Singleton类的成员是静态的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆