簡體   English   中英

在同一個類的構造函數中傳遞類的對象

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

如何用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()
    }
}

您可以添加另一個手動提供值的構造函數:

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

初始代碼不起作用的原因是,當您創建需要相同類型的另一個實例的對象時,依賴關系鏈會上升到無窮大,您永遠不會有起點。

通過使用手動構造函數,您可以手動創建起始點,換句話說,是其他對象可以依賴的初始對象。 因此,您消除了無限的依賴鏈。

你不能像這樣初始化一個類:它需要一個自己的實例才能被初始化,呈現雞與蛋的問題。

請注意,您無法構造派生類並將其傳遞給Student的構造函數,因為派生類必須調用復制構造函數。

解決這個問題的唯一方法是添加一個不同於你的構造函數,並調用它:

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

或者添加默認構造函數,並使用屬性初始值設定項調用它:

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

讓一個類的唯一構造函數需要一個類的實例是沒有意義的,並且你肯定需要一些其他類型的構造函數才能使用一個(否則你永遠不能創建那個初始實例)。

然而,有一點確實有意義的是使用靜態方法從現有類創建類的新實例。

下面的示例沒有定義任何顯式構造函數,因此使用默認構造函數並顯式設置類值:

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

要使用此方法,您首先要創建一個學生:

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

然后,要從這個創建一個新學生,我們可以調用我們的靜態方法:

var studentTwo = Student.CreateFrom(studentOne);

但是現在我們有兩個同一個Id的學生。 也許這不是我們想要的,所以最好讓一個只讀的StudentId從私有靜態支持字段自動設置。 我們可以使用lock對象來確保我們不會為多個學生分配相同的ID。 我們也可以覆蓋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}";
    }
}

現在我們不需要設置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();
}

產量

在此輸入圖像描述

你需要一些方法來初始化沒有那個構造函數的對象。 因此,使用具有內聯初始化的默認構造函數來創建初始學生,然后允許您使用其現有實例創建其他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

您的代碼令人困惑,您只需要在構造函數中傳遞參數而不是對象,但是您嘗試這樣做的方式,您需要在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);
}

但請注意 ,這將使您的代碼編譯甚至工作,但這對於執行簡單的操作而非內存效率來說是太多額外的東西,因為我們創建了一個根本不需要的額外實例。

所以你只需要在StudentIdName的構造函數中有參數,如S. Tarik的答案所示。

那樣你的構造函數看起來像:

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

希望它能讓您了解如何解決這個問題。

謝謝!

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