zoukankan      html  css  js  c++  java
  • dotnet使用误区<初始化类的问题>

    在dotnet 3.0后提供了自动属性和初始化器的功能。

    自动属性如下2-4行,为什么如此简洁,据了解是因为C#编译器遇上象上面这样的空的get/set属性的话,它会自动为我们在类中生成一个私有成员变量,对这个变量实现一个公开的getter 和setter。

    初始化器如下第5行,即可以通过属性或则声明为public的成员变量来初始化一个类。

    View Code
    1 publicclass Person {
    2 publicstring FirstName { get; set; }
    3 publicstring LastName { get; set; }
    4 publicint Age { get; set; }
    5 Person person =new Person { FirstName="Scott", LastName="Guthrie", Age=32 };
    6 }

    这些确实带来了一些便利之处。

    当我们为这些新特性带来的便利感到兴奋时,这其中隐含的陷阱也就悄然浮现。

    那么,'初始化器'new出来的类也应该与'构造函数'new出来的类同等吧,事实却泼了我一盆冷水。

    初始化器与构造函数在初始化类时所达到的效果并不完全相同。

    请看代码:

    publicclass FileInfo
    {
    publicstaticevent EventHandler<ProgressValueArgs> OnProgressValueChanged;
    privatelong offset;

    public FileInfo()
    {
    }
    public FileInfo(long offset, long size)
    {
    this.offset = offset;
    this.Size = size;
    }

    publiclong Offset
    {
    get
    {
    return offset;
    }
    set
    {
    //当offset被赋值时将会引发事件,事件将会把该类本身作为参数传递给事件的接收者
    if (null!= OnProgressValueChanged)
    OnProgressValueChanged(
    this, new ProgressValueArgs(this));

    offset
    = value;
    }
    }

    publiclong Size
    {
    get;
    set;
    }
    }

    当分别使用对象初始化器赋值方式一、,结果却不同

     1 public class Class1{
    2
    3      public Class1
    4 {
    5       //对象初始化器赋值方式一
    6 FileInfo fileinfo =new FileInfo(){Offset=-1,Size=-2};
    7       //对象初始化器赋值方式二
    8       fileinfo = new FileInfo(){Size=-2,Offset=-1};
    9 FileInfo.OnProgressValueChanged +=new EventHandler<ProgressValueArgs>(Download_OnProgressValueChanged);
    10 }
    11
    12      privatevoid Download_OnProgressValueChanged(object sender, ProgressValueArgs e)
    13 {
    14 System.Console.WriteLine(String.Format("OFFSET:{0}大小{1}", e.FileInfo.Id, e.FileInfo.Offset, e.FileInfo.Size));
    15 }
    16 }

    上述情况的原因很简单 ,第一种赋值方式中,事件是在Offset被赋值后就发生了,并在Size被赋值前事件就已经结束。第二种赋值方式中,事件是在Size,Offset都赋值后才发生的,所以产生的结果也就不同。

    正确的代码如下:

    publicclass FileInfo
    {
    publicstaticevent EventHandler<ProgressValueArgs> OnProgressValueChanged;
    privatelong offset;

    public FileInfo()
    {
    }
    public FileInfo(long offset, long size)
    {
    this.offset = offset;
    this.Size = size;
    }
    publiclong Offset
    {
    get
    {
    return offset;
    }
    set
    {
    //当offset被赋值时将会引发事件,事件将会把该类本身作为参数传递给事件的接收者
    if ( null!= OnProgressValueChanged && true == isSizeChanged ){
    OnProgressValueChanged(
    this, new ProgressValueArgs(this));
                            isSizeChanged = false;
                                          }

    offset
    = value;
    }
    }
    private long size;
       private bool isSizeChanged;

    publiclong Size
    {
    get{return size;}
    set{
            size = value;
            isSizeChanged = true;
            }        
            }               
    }

    也就是为事件所依赖的其余变量设立一个标志,这些标志应该作为事件是否被引发的条件。

  • 相关阅读:
    单例模式
    HashSet、LinkedHashSet、SortedSet、TreeSet
    ArrayList、LinkedList、CopyOnWriteArrayList
    HashMap、Hashtable、LinkedHashMap
    andrew ng machine learning week8 非监督学习
    andrew ng machine learning week7 支持向量机
    andrew ng machine learning week6 机器学习算法理论
    andrew ng machine learning week5 神经网络
    andrew ng machine learning week4 神经网络
    vue组件监听属性变化watch方法报[Vue warn]: Method "watch" has type "object" in the component definition. Did you reference the function correctly?
  • 原文地址:https://www.cnblogs.com/tao_/p/2121374.html
Copyright © 2011-2022 走看看