简体   繁体   English

在同一个类的构造函数中传递类的对象

[英]Passing object of class in constructor of the same class

How do you initialize a class like this with say StudentId = 1 and Name = "Alex" 如何用StudentId = 1和Name =“Alex”初始化这样的类

class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }

    public Student(Student student)
    {
        StudentId = student.StudentId;
        Name = student.Name;
    }
}
class Program
{
    static void Main(string[] args)
    {
        Student s = new Student()
    }
}

You can add another constructor in which you supply values manually: 您可以添加另一个手动提供值的构造函数:

public Student(int id, string name)
{
    StudentId = id;
    Name = name;
}

The reason your initial code doesn't work is, when you are creating an object that needs another instance of the same type, the dependency chain goes up to infinity and you can never have a start point. 初始代码不起作用的原因是,当您创建需要相同类型的另一个实例的对象时,依赖关系链会上升到无穷大,您永远不会有起点。

By having a manual constructor, you can manually create a start point, in other words, an initial object that other objects can depend on. 通过使用手动构造函数,您可以手动创建起始点,换句话说,是其他对象可以依赖的初始对象。 Therefore you eliminate infinite dependency chain. 因此,您消除了无限的依赖链。

You cannot initialize a class like that: it requires an instance of itself in order to be initialized, presenting a chicken-and-egg problem. 你不能像这样初始化一个类:它需要一个自己的实例才能被初始化,呈现鸡与蛋的问题。

Note that you cannot construct a derived class and pass it to Student 's constructor, because the derived class would have to call the copy constructor. 请注意,您无法构造派生类并将其传递给Student的构造函数,因为派生类必须调用复制构造函数。

The only way around this issue is to add a constructor other than the one you have, and call it: 解决这个问题的唯一方法是添加一个不同于你的构造函数,并调用它:

public Student(int id, string name) {
    StudentId = id;
    Name = name;
}

or to add a default constructor, and call it with property initializers: 或者添加默认构造函数,并使用属性初始值设定项调用它:

public Student() {}
...
var student = new Student {Id = 1, Name = "Alex" };

It doesn't really make sense to have the only constructor for a class require an instance of the class, and you would definitely need some other type of constructor in order to use one (otherwise you can never create that initial instance). 让一个类的唯一构造函数需要一个类的实例是没有意义的,并且你肯定需要一些其他类型的构造函数才能使用一个(否则你永远不能创建那个初始实例)。

One thing that does make sense, however, is to have a static method that creates a new instance of the class from an existing class. 然而,有一点确实有意义的是使用静态方法从现有类创建类的新实例。

The example below does not have any explicit constructor defined, so the default constructor is used and the class values are set explicitly: 下面的示例没有定义任何显式构造函数,因此使用默认构造函数并显式设置类值:

class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }

    public static Student CreateFrom(Student student)
    {
        return new Student { StudentId = student.StudentId, Name = student.Name };
    }
}

To use this method, you would first create a student: 要使用此方法,您首先要创建一个学生:

var studentOne = new Student { StudentId = 1, Name = "Bob"};

Then, to create a new student from this one, we can call our static method: 然后,要从这个创建一个新学生,我们可以调用我们的静态方法:

var studentTwo = Student.CreateFrom(studentOne);

But now we have two students with the same Id. 但是现在我们有两个同一个Id的学生。 Perhaps that's not really what we want, so it might be better to have an read-only StudentId that gets set automatically from a private static backing field. 也许这不是我们想要的,所以最好让一个只读的StudentId从私有静态支持字段自动设置。 We can use a lock object to ensure we don't assign the same id to more than one student. 我们可以使用lock对象来确保我们不会为多个学生分配相同的ID。 Also we can override the ToString method so it displays the Id and Name of the student: 我们也可以覆盖ToString方法,以便显示学生的Id和Name:

class Student
{
    // This lock object is used to ensure we don't 
    // assign the same Id to more than one student
    private static readonly object IdLocker = new object();

    // This keeps track of next available student Id
    private static int nextStudentId;

    // Read only
    public int StudentId { get; }

    public string Name { get; set; }

    // Default constructor automatically sets the student Id
    public Student()
    {
        lock (IdLocker)
        {
            // Assign student id and incrment the next avaialable
            StudentId = nextStudentId;
            nextStudentId++;
        }
    }

    public static Student CreateFrom(Student student)
    {
        return new Student { Name = student.Name };
    }

    public override string ToString()
    {
        return $"Student {StudentId}: {Name}";
    }
}

Now we don't need to set the id, and we can see that it automatically increments for us: 现在我们不需要设置id,我们可以看到它会自动递增:

private static void Main()
{
    var studentOne = new Student { Name = "Bob" };
    var studentTwo = Student.CreateFrom(studentOne);

    Console.WriteLine(studentOne);
    Console.WriteLine(studentTwo);

    Console.Write("\nDone!\nPress any key to exit...");
    Console.ReadKey();
}

Output 产量

在此输入图像描述

You need some way of initializing the object without that constructor. 你需要一些方法来初始化没有那个构造函数的对象。 So using a default constructor with inline initialization to create the initial student, then lets you create other Student objects using already existing instances of it. 因此,使用具有内联初始化的默认构造函数来创建初始学生,然后允许您使用其现有实例创建其他Student对象。

using System;

public class Program
{
    public static void Main()
    {
        var s = new Student {
            StudentId = 1,
            Name = "Alex"
        };

        var s2 = new Student(s);

        Console.WriteLine(s2.StudentId);
        Console.WriteLine(s2.Name);
    }
}

class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }

    public Student() {}

    public Student(Student student)
    {
        StudentId = student.StudentId;
        Name = student.Name;
    }
}

DotNetFiddle DotNetFiddle

Your code is confusing, you just need to pass in constructor the parameters instead of an object, but the way you are trying to do, you would need to set first properties on the instance created in Main program and then pass the instance like, but you will also need to add a parameter-less constructor too: 您的代码令人困惑,您只需要在构造函数中传递参数而不是对象,但是您尝试这样做的方式,您需要在Main程序中创建的实例上设置第一个属性,然后传递实例,但是你还需要添加一个无参数的构造函数:

class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }

    // Note: parameterless constructor here
    public Student()
    {


    }

    public Student(Student student)
    {
        StudentId = student.StudentId;
        Name = student.Name;
    }
}
static void Main(string[] args)
{
        Student s = new Student(); // parameter less constructor
        s.StudentId = 1;
        s.Name = "Alex";

       Student s2 = new Student(s);
}

But note that This will make your code compile and even work, but this is too much of extra stuff for doing simple thing and not memory efficient as there is one extra instance we have created which is not needed at all. 但请注意 ,这将使您的代码编译甚至工作,但这对于执行简单的操作而非内存效率来说是太多额外的东西,因为我们创建了一个根本不需要的额外实例。

so you just need to have parameters in the constructor for StudentId and Name like S. Tarik's answer showed. 所以你只需要在StudentIdName的构造函数中有参数,如S. Tarik的答案所示。

That way your constructor would look like: 那样你的构造函数看起来像:

public Student(int studentId, string name)
{
    StudentId = studentId;
    Name = name;
}

Hope it gives you the idea how to approach this problem. 希望它能让您了解如何解决这个问题。

Thanks! 谢谢!

public class Student
{ 
  public int Id {get; set;}
  public string Name {get; set; }

  public Student(object o) 
  {
    Student student = o as Student;
    if (student != null)
    {
       Id = student.Id;
       Name = student.Name;
    }

    // other cases to build a User copy
    string json = o as string;
    if (json != null) 
    {
         Student student = JsonConvert.Deserialize<Student>(json);
         Id = student.Id;
         Name = student.Name;
    }

  }

  public Student() 
      : this(null)
  {

  }

  public Student(int id, string name) 
      this(null)
  {
      Id = id;
      Name = name;
  }
}



static void Main(string[] args) 
{
     Student student = new Student(7634, "Jim");

     // build a copy
     Student copy = new Student(student);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM