初始化类字段的字段定义还是在类的构造函数 [英] Initializing Class Fields at the Field Definition or in Class Constructor

查看:98
本文介绍了初始化类字段的字段定义还是在类的构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有需要时,对象被初始化时,如需要之前可以添加/从它除去的对象被创建的列表被初始化字段的类



 公共类MyClass1的
{
私有列表< MyOtherClass> _otherClassList;

公共MyClass1的()
{
this._otherClasslist =新的List< MyOtherClass>();
}
}


公共类MyClass2
{
私有列表< MyOtherClass> =新的List< MyOtherClass>();

公共MyClass2()
{
}
}

什么是这两个类之间的区别,以及为什么你会选择比其他?



的一种方法

我通常设置在构造方面,在MyClass1的,因为我觉得它更容易能够在一个地方看到所有的对象被实例化时发生的东西看,但有它在哪里不如直接在MyClass2初始化一个领域像任何情况下<? / p>

解决方案

由C#编译器(VS2008 SP1)发出的离子液体就几乎等同于这两种情况下(甚至在调试和发布版本)。



然而,如果你的需要补充的是采取 名单,LT参数化的构造; MyOtherClass> 作为参数,这将是不同的(尤其是,当你将创建一个显著大量的对象与这样的构造函数)。过去VS和构建它看到的

请参阅下面的例子中看到的不同(可以复制和放大器-gate.com/products/reflector/\">Reflector ILDASM )。

 使用系统; 
使用System.Collections.Generic;

命名空间构建函数
{
//与VS2008 SP1
等级A
{
测试//这将进入任何构造函数之前被执行机构...
私有列表<串GT; myList中=新名单<串GT;();

公开发行A(){​​}

//这将创建一个未使用的临时名单,LT;字符串>目标
//在这两个调试和发布版本
公开发行A(列表<串GT;清单)
{
myList中=清单;
}
}

类B
{
私有列表<串GT; myList中;

。通过C#编译器发出//离子液体identicial在两个调试
//这些公共A()和发行版本
公众B()
$ { b $ b = myList中新的List<串GT;();
}

//没有垃圾在这里
公众B(名单<串GT;清单)
{
myList中=清单;
}
}

类C
{

私人列表<串GT; myList中= NULL;
//在发布版本,这等同于B(),
//在调试版本,离子液体初始化myList上,以空插入。
//比乙因此,更多的ILS()的调试版本。
公共C()
{
myList中=新名单<串GT;();
}

//这是相同的B(名单<串GT;清单)
//在这两个调试和发布版本。
公共C(名单<串GT;清单)
{
myList中=清单;
}
}
$ B $ D B类
{
//这会在进入try / catch块
//前执行默认的构造函数
私人电子邮件MYE =新E();
公众D()
{

{}
赶上(NotImplementedException E)
{
//不能赶上NotImplementedException用E抛出()。
Console.WriteLine(我能赶上在这里?);
}
}
}

公共类E
{
公共E()
{
抛出新NotImplementedException();
}
}

类节目
{
静态无效的主要(字串[] args)
{
//这将导致未处理的异常。
//你可能需要使用try / catch块构造三维物体时。
D MYD =新D();
}
}
}

注意:切换到发布版本的时候我并没有改变任何优化标志。


I have a class with a field that needs to be initialized when the object is initialized, such as a list that needs to be created before objects can be added/removed from it.

public class MyClass1
{
    private List<MyOtherClass> _otherClassList;

    public MyClass1()
    {
        this._otherClasslist = new List<MyOtherClass>();
    }
}


public class MyClass2
{
    private List<MyOtherClass> = new List<MyOtherClass>();

    public MyClass2()
    {
    }
}

What is the difference between these two classes, and why would you choose one method over the other?

I usually set the field in the constructor, as in MyClass1, because I find it easier to be able to look in one place to see all the stuff that happens when the object is being instantiated, but is there any case where it is better to initialize a field directly like in MyClass2?

解决方案

The ILs emitted by C# compiler (VS2008 sp1) will be almost equivalent for both cases (even in Debug and Release builds).

However, if you need to add parameterized constructors that take List<MyOtherClass> as an argument, it will be different (especially, when you will create a significantly large number of objects with such constructors).

See the following examples to see the differences (you can copy&past to VS and build it to see ILs with Reflector or ILDASM).

using System;
using System.Collections.Generic;

namespace Ctors
{
    //Tested with VS2008 SP1
    class A
    {
        //This will be executed before entering any constructor bodies...
        private List<string> myList = new List<string>();

        public A() { }

        //This will create an unused temp List<string> object 
        //in both Debug and Release build
        public A(List<string> list)
        {
            myList = list;
        }
    }

    class B
    {
        private List<string> myList;

        //ILs emitted by C# compiler are identicial to 
        //those of public A() in both Debug and Release build 
        public B()
        {
            myList = new List<string>();
        }

        //No garbage here
        public B(List<string> list)
        {
            myList = list;
        }
    }

    class C
    {

        private List<string> myList = null;
        //In Release build, this is identical to B(), 
        //In Debug build, ILs to initialize myList to null is inserted. 
        //So more ILs than B() in Debug build.  
        public C()
        {
            myList = new List<string>();
        }

        //This is identical to B(List<string> list) 
        //in both Debug and Release build. 
        public C(List<string> list)
        {
            myList = list;
        }
    }

    class D
    {
        //This will be executed before entering a try/catch block
        //in the default constructor
        private E myE = new E();
        public D()
        {
            try
            { }
            catch (NotImplementedException e)
            {
                //Cannot catch NotImplementedException thrown by E(). 
                Console.WriteLine("Can I catch here???");
            }
        }
    }

    public class E
    {
        public E()
        {
            throw new NotImplementedException();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //This will result in an unhandled exception. 
            //You may want to use try/catch block when constructing D objects.
            D myD = new D();
        }
    }
}

Note: I did not change any optimization flag when switching to Release build.

这篇关于初始化类字段的字段定义还是在类的构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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