C#中的构造函数

时间:2016-04-13 14:56:36

标签: c# constructor

我一直在阅读很多关于为什么构造函数是有用的,并且我发现的所有资源都指定构造函数用于初始化类的实例。使用构造函数的一个主要好处是它保证对象在使用之前将经过适当的初始化,通常接受参数。它有助于确保对象的完整性,并有助于使用面向对象语言编写的应用程序更加可靠。

默认情况下,如果在类中没有指定构造函数,则在C#中实例化默认的空构造函数。

我发现的大多数例子都指明了这样的内容;

public Car(int speedCurrent, int gearCurrent) {
    speed = speedCurrent;
    gear= startGear;
}

Car myCar = new Car(0, 0);

现在,当您可以指定属性时,创建构造函数的实际意义是什么;

public int speed { get; set; }
public int gear { get; set; }

并像这样初始化它;

Car myCar = new Car();
myCar.speed = 0;
myCar.gear = 0;

我不能满足于明确创建构造函数的需要。如果有人能给我一个很好的实际例子,我将不胜感激。

10 个答案:

答案 0 :(得分:10)

虽然您可以像显示的那样初始化属性:

Car myCar = new Car();
myCar.speed = 0;
myCar.gear = 0;

没有构造函数,您也可以选择 not 来初始化任何属性

Car myCar = new Car();

这可能导致班级工作不佳/根本不工作。

在允许使用类实例之前,构造函数的目的是强制初始化所有所需的属性(按设计)。

如果您考虑在具有多个团队成员的项目中工作的情况,这将特别有用。如果您的团队成员想要使用您的class,通过拥有正确的构造函数,您可以向他们提示需要在class中初始化哪些属性,以便他们正确使用该类。

答案 1 :(得分:4)

  

现在,当你创建构造函数的实际意义是什么   可以指定属性;

拥有非默认构造函数的好处是您必须将所有必需的依赖项传递给它。这保证了在实例化时,对象将拥有正常运行所需的一切。

答案 2 :(得分:2)

  

现在,当你可以指定属性

时,创建构造函数的实际意义是什么

该方法暴露属性有四个问题:

  • 初始化后无法保证一致性 - 例如,如果要确保非零速度需要非零档位,则无法再控制此检查
  • 当必须以原子方式更新多个属性时,无法确保一致性 - 在同时发生的情况下speedgear必须同时更新,同时由锁定保护具有独立暴露属性的方法并不可靠
  • 您被迫使您的对象可变 - 这并不总是令人满意的,尤其是当您的对象设计为并发使用时
  • 您必须公开用户可能不需要的方法 - 即使在用户期望可变对象的情况下,也可能不希望公开单个setter;用这种方法你别无选择。
  

我不能满足于明确创建构造函数的需要。

以下简要介绍了当您的二传手未曝光时您可以采取的措施:

class Car {
    private readonly object lockObject = new object();
    private int speed;
    private int gear;
    public int Speed {
        lock (lockObject) {
            return speed;
        }
    }
    public int Gear {
        lock (lockObject) {
            return gear;
        }
    }
    public int Gear{ get; }
    public Car(int speed, int gear) {
        // You can validate two attributes together
        if (speed != 0 && gear == 0) {
            throw new ArgumentException("Non-zero speed in zero gear");
        }
        this.speed = speed;
        this.gear= gear;
    }
    public void SpeedUp(int increase) {
        lock(lockObject) {
            var newSpeed = Math.Max(Speed + increase, 0);
            if (newSpeed > 200) {
                 throw new InvalidOperationexception("Cannot speed up past 200");
            }
            // Concurrent users would not see inconsistent speed setting
            Speed = newSpeed;
            Gear = Speed / 25;
        }
    }
}

主要优点是能够在并发环境中同时进行调整,以及确保初始对象一致性的方法。

答案 3 :(得分:1)

您的示例中的实际要点是您不需要执行Request.RequestContent进行实例化,而只需执行此操作以进行默认初始化:

new Car(0, 0);

答案 4 :(得分:1)

非默认构造函数强制您的类的客户端提供参数。按属性初始化 a)代码不要求 b)可以暴露尚未准备好使用的类。 此外,您可能希望隐藏其他人的速度或装备属性。

答案 5 :(得分:1)

根据您的课程的不同,您可能需要进行一些初始化。例如,一个类可能在初始化时挂钩静态事件,或者输出到debug ..在编码时它也为你提供了一个点,你可以设置一个断点来打破任何实例化类的尝试。

答案 6 :(得分:1)

问题在于,您的Car类用户需要知道他们需要设置汽车的初始速度和档位。

我遵循的规则指南是构造函数应该创建一个100%准备使用的对象。

答案 7 :(得分:1)

建造者的概念是相当古老的学校。当你自己管理所有指针时,它可以追溯到C和C ++时代。构造函数将设置大多数可填充变量,以确保在执行代码时没有获得一般保护错误或分段错误。

现代编码器避免使用参数的构造函数。这是由于他们在执行自动化单元测试时遇到的困难。完全可以使用只有默认构造函数的类(没有参数的构造函数),并在事后调用属性或方法对它们进行初始化。

答案 8 :(得分:1)

我想说这可以归结为你想要如何实现你正在构建的课程的目标。

在OO编程中实现封装,您只能通过getter / setter访问成员。这又取决于您希望实施OO主体的程度。

如果在构造函数中有一些需要这些值的初始化代码,那么应该将变量传递给构造函数的示例。

private int speed { get; set; }
private int gear { get; set; }
private bool reduceSpeed { get; set; }

public Car(int speedCurrent, int gearCurrent) {
    speed = speedCurrent;
    gear= startGear;
    if (speed > 30)
        reduceSpeed = true; // do further processing with this.
    ...
}

答案 9 :(得分:0)

C# 中的构造函数:(简单的理论)

  • 是一种特殊类型的函数/方法,与其同名 类。
  • 每当创建类的对象时,它就会自动调用。
  • 它还负责对象初始化和内存 其类成员的分配。
  • 它没有返回类型,没有 甚至是 void 类型。
  • 支持使用参数化构造函数进行重载。

它们有 4 种类型:

enter image description here

默认构造函数:

默认构造函数没有参数。当一个类没有构造函数时,编译器会为该类提供默认构造函数。如果你没有定义任何构造函数,那么默认构造函数是由编译器定义的。用于为类的实例变量分配默认值

示例:

namespace Default_parameterizedConstructor
{
    public class Student
    {
        // instance members
        public int StudentId { get; set; }
        public string Name { get; set; }
        public string College { get; set; }

        //default constructor parameters less
        public Student()
        {
            College = "My College"; //explicit default value for college
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //Object instance of Student.
            Student st = new Student();
            Console.WriteLine("Student details are Student ID: {0}, Student Name: {1}, College :{2}", st.StudentId, st.Name, st.College);
            Console.ReadKey();
        }
    }
}

默认构造函数的输出将是:“学生详细信息是学生 ID:0,学生姓名:,学院:我的学院”

参数化构造函数: 参数化构造函数具有一个或多个参数。当我们必须传递一个或多个参数时使用,以便我们可以设置类实例成员的参数。用于为类的实例变量赋值。当实例成员名称和构造函数接收参数相同时,我们使用 this 关键字,在这种情况下,必须指定 this 关键字。如果名称不同,则可以选择使用此关键字。

现在,让我们以参数化构造函数为例:

namespace Default_parameterizedConstructor
{

    public class Student
    {
        // instance members
        public int StudentId { get; set; }
        public string Name { get; set; }
        public string College { get; set; }

        //default constructor parameters less
        public Student()
        {
            College = "My College"; //explicit default value for college
        }
        // parameterised constructor
        public Student(int studentid, string name, string college)
        {
            this.StudentId = studentid;
            this.Name = name;
            this.College = college;

        }
        public Student(int studentid, string name)
        {
            this.StudentId = studentid;
            this.Name = name;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //default constructor parameter
            //Object instance of Student.
            Student st = new Student();
            Console.WriteLine("The output for Default Constructor are Student ID: {0}, Student Name: {1}, College :{2}", st.StudentId, st.Name, st.College);
            
            
            // parameterised constructor
            //Operator overloading happening.
            Student st1 = new Student(1, "John Doe", "MIT");
            Console.WriteLine("The output for Default Constructor are Student ID: {0}, Student Name: {1}, College :{2}", st1.StudentId, st1.Name, st1.College);

            // parameterised constructor with operator overloading
            Student st2 = new Student(1,"Jimmy");
            Console.WriteLine("The output for Default Constructor are Student ID: {0}, Student Name: {1}, College :{2}", st2.StudentId, st2.Name, st2.College);

            Console.ReadKey();
        }
    }
}

*输出如下: //第一次

默认构造函数的输出是学生 ID:0,学生姓名:,学院:我的学院

//第二个

默认构造函数的输出是学生 ID:1,学生姓名:John Doe,学院:MIT

//第三

默认构造函数的输出是学生 ID:1,学生姓名:Jimmy,学院:*

静态构造函数: 在创建类的第一个对象之前调用的一种特殊类型的构造函数。 用于初始化任何静态字段,或执行只需要执行一次的特定操作。 一个类只能有一个静态构造函数,并且必须是默认构造函数,没有访问修饰符。

私有构造函数: 限制类外部实例化,但在嵌套类中,您可以创建此类的实例。 在 C# 1 X 中没有静态类,因此开发人员使用私有构造函数来防止类外部实例化。 用于实现单例模式,即类的单个实例。 一个类可以有多个私有构造函数和公共构造函数。

如果您不创建实例,您将如何访问该值? 我们可以通过将类的成员设置为私有静态来做到这一点。使用类名只能使用静态成员。

让我们通过下面的例子来看看:

namespace StaticAndPrivate
{
    public class Example
    {
        private static int Counter;

        //private constructor
        private Example()
        {
            Counter = 10;
        }

        //static constructor
        static Example()
        {
            Counter = 20;
        }

        //public constructor
        public Example(int counter)
        {
            Counter = Counter + counter;
        }

        public static int GetCounter()
        {
            return ++Counter;
        }

        public class NestedExample
        {
            public void Test()
            {
                //internal instance
                Example ex = new Example();
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //external instance
            //Example ex = new Example();

            Example ex = new Example(10);
            Console.WriteLine("Counter : {0}", Example.GetCounter());

            Console.ReadKey();
        }
    }
}

希望这通过一个例子来解释这个概念。