如何在C#中使用icloneable接口

编程入门 行业动态 更新时间:2024-10-27 00:32:36
本文介绍了如何在C#中使用icloneable接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 嘿,我正在尝试克隆一个对象。 更新学生分数表单应创建当前学生对象的克隆,然后将更改应用于克隆。这样,只有当用户单击确定按钮时,更改才会保存到当前学生。要创建克隆,Student类需要实现ICloneable接口,而Clone方法需要实现深层复制。到目前为止,我已经了解到,当您需要原始包含的其他对象的副本(而不是指向原始对象的位置的指针)时,您需要深层复制某些内容,以便在进行更改时这些复制的属性,不会影响原始对象。我正在努力的是把它应用到我的模型中。下面是我正在尝试克隆的学生班级和更新学生表格。如果有帮助,我还附上了源代码。谢谢! SourceCode GitHub - Triptonix /帮助 [ ^ ] Student.cs

public class Student { public List< int>分数=新列表< int>(); 公共字符串名称 {get;组; } public bool AddScore(int score) { try { Scores.Add(score); } catch {return false; } 返回true; } public List< int> GetScores() {返回分数; } public int GetScoreAt(int index) { return(int)得分[index]; } public int GetScoreTotal() { int sum = 0; foreach(得分中的int得分) { sum + =得分; } 返还金额; } public int GetScoreCount() { return Scores.Count; } public int GetScoreAverage() { return GetScoreTotal()/ GetScoreCount(); } public void DestroyScores() { Scores = new List< int>(); } }

frmUpdateScores.cs

公开partial class frmUpdateStudent:Form { private Form1 parentForm; //主要形式私人学生studentToEdit; //学生列表 private int index; // index public frmUpdateStudent(Form1 parentForm,int index)//用新学生更新父表单(Form1)并得分 { this.parentForm = parentForm; this.index = index; studentToEdit = this.parentForm.GetStudent(index); InitializeComponent(); StudentName.Text = studentToEdit.Name; UpdateScoreDisplay(); } public void AddScoreToStudent(int value)//为当前学生添加分数并显示在列表 { studentToEdit.AddScore(value); UpdateScoreDisplay(); } public void UpdateScoreAtIndex(int id,int value)//更新从列表中选择的分数 { studentToEdit.GetScores()[id] =值; UpdateScoreDisplay(); } public int GetScoreAtIndex(int id)//得分指数 { return studentToEdit.GetScoreAt(id); } private void UpdateScoreDisplay()//更新分数显示列表 { CurrentScores.DataSource = null; CurrentScores.DataSource = studentToEdit.GetScores(); } private void AddScoreButton_Click(object sender,EventArgs e)//打开添加分数表格 { frmAddScore addScoreForm = new frmAddScore(this); addScoreForm.Show(); } private void RemoveScoreButton_Click_1(object sender,EventArgs e)//从当前索引中删除分数并更新显示列表 { studentToEdit.GetScores()。 RemoveAt移除(CurrentScores.SelectedIndex); UpdateScoreDisplay(); } private void ClearScoresButton_Click_1(object sender,EventArgs e)//清除所有分数 { studentToEdit.DestroyScores(); UpdateScoreDisplay(); } private void CloseButton_Click_1(object sender,EventArgs e) { Close(); //关闭表单} private void UpdateButton_Click_1(对象发件人,EventArgs e)//为当前学生打开更新表单 {学生表1 =新学生( ); Form1.Name = StudentName.Text; parentForm.UpdateStudent(index,Form1); 关闭(); } private void UpdateScoresButton_Click(object sender,EventArgs e) { frmUpdateScore updateScoreForm = new frmUpdateScore(this,CurrentScores.SelectedIndex); updateScoreForm.Show(); } }

我尝试了什么: 我试图克隆该类,但不确定如何仅将更改应用于克隆,这样,更改将仅保存到当前学生如果用户单击OK按钮

解决方案

无论如何都不引用值类型(int,bool)。字符串是不可变的,它们也没有被引用。如果你有一个想要深层复制的类,并且它包含类实例,你需要构建该类的新实例,否则它们将被引用

有时它更容易实现它自己;看看你是否从中获得了一些想法:

使用System; 使用System.Collections.Generic; namespace YourNameSpace { public class Student { public List< int>成绩; public Student CloneOf; public Student(string name,params int []得分) { CloneOf = null; 姓名=姓名; 分数=新名单< int>(分数); } public string Name {get;组; } public bool AddScore(int score) { try { Scores.Add(score); } catch {return false; } 返回true; } public List< int> GetScores() {返回分数; } public int GetScoreAt(int index) { return(int)得分[index]; } public int GetScoreTotal() { int sum = 0; foreach(得分中的int得分) { sum + =得分; } 返还金额; } public int GetScoreCount() { return Scores.Count; } public int GetScoreAverage() { return GetScoreTotal()/ GetScoreCount(); } public void DestroyScores() { Scores = new List< int>(); } } public static class StudentExtensions { public static Student Clone(this Student stdnt) { var clone = new学生( stdnt.Name, stdnt.Scores.ToArray()) //注意在这里使用对象初始化程序 { CloneOf = stdnt }; 返回克隆; } public static void SaveEdits(this Student stdnt,Student clone) { if(clone == null || clone.CloneOf == null || clone.CloneOf!= stdnt) {抛出新的ArgumentException(无效的克隆参数); } if(stdnt.Scores!= clone.Scores)stdnt.Scores = clone.Scores; if(stdnt.Name!= clone.Name)stdnt.Name = clone.Name; //考虑在这里处理克隆? } } }

用法示例:

学生s1 =新学生(S1,89,92,100,78); 学生s2 = s1.Clone(); s2.Scores [2] = 87; s1.SaveEdits(s2);

Hey, I'm attempting to clone an object. The Update Student Scores form should create a clone of the current student object and then apply changes to the clone. That way the changes will be saved to the current student only if the user clicks the OK button. To create a clone, the Student class will need to implement the ICloneable interface, and the Clone method will need to implement a deep copy. So far, I've learned that you want a deep copy of something when you need a copy of the other objects contained by the original (rather than pointers to the location of those objects in the original), so that when you make changes to these copied properties, you don't affect the original object. What I'm struggling with though is applying it to my model. Below is the student class I'm trying to clone and the update student form. I've also attached the source code if that helps. Thanks! SourceCode GitHub - Triptonix/Help[^] Student.cs

public class Student { public List<int> Scores = new List<int>(); public string Name { get; set; } public bool AddScore(int score) { try { Scores.Add(score); } catch { return false; } return true; } public List<int> GetScores() { return Scores; } public int GetScoreAt(int index) { return (int)Scores[index]; } public int GetScoreTotal() { int sum = 0; foreach (int score in Scores) { sum += score; } return sum; } public int GetScoreCount() { return Scores.Count; } public int GetScoreAverage() { return GetScoreTotal() / GetScoreCount(); } public void DestroyScores() { Scores = new List<int>(); } }

frmUpdateScores.cs

public partial class frmUpdateStudent : Form { private Form1 parentForm; //main form private Student studentToEdit; //student list private int index; //index public frmUpdateStudent(Form1 parentForm, int index) //update parent form (Form1) with the new student and scores { this.parentForm = parentForm; this.index = index; studentToEdit = this.parentForm.GetStudent(index); InitializeComponent(); StudentName.Text = studentToEdit.Name; UpdateScoreDisplay(); } public void AddScoreToStudent(int value) //add score to current student and display in the list { studentToEdit.AddScore(value); UpdateScoreDisplay(); } public void UpdateScoreAtIndex(int id, int value) //update a score selected from the list { studentToEdit.GetScores()[id] = value; UpdateScoreDisplay(); } public int GetScoreAtIndex(int id) //get the score index { return studentToEdit.GetScoreAt(id); } private void UpdateScoreDisplay() //update the score display list { CurrentScores.DataSource = null; CurrentScores.DataSource = studentToEdit.GetScores(); } private void AddScoreButton_Click(object sender, EventArgs e) //open the add score form { frmAddScore addScoreForm = new frmAddScore(this); addScoreForm.Show(); } private void RemoveScoreButton_Click_1(object sender, EventArgs e) //remove a score from current index and update display list { studentToEdit.GetScores().RemoveAt(CurrentScores.SelectedIndex); UpdateScoreDisplay(); } private void ClearScoresButton_Click_1(object sender, EventArgs e) //clear all scores { studentToEdit.DestroyScores(); UpdateScoreDisplay(); } private void CloseButton_Click_1(object sender, EventArgs e) { Close(); //close form } private void UpdateButton_Click_1(object sender, EventArgs e) //open update form for current student { Student Form1 = new Student(); Form1.Name = StudentName.Text; parentForm.UpdateStudent(index, Form1); Close(); } private void UpdateScoresButton_Click(object sender, EventArgs e) { frmUpdateScore updateScoreForm = new frmUpdateScore(this, CurrentScores.SelectedIndex); updateScoreForm.Show(); } }

What I have tried: I've tried to clone the class, but not sure how to apply the changes only to the clone so that way, the changes will be saved to the current student only if the user clicks the OK button

解决方案

Value types are not referenced anyhow (int, bool). strings are immutable, they are also not referenced. If you have a class you want to deep copy, and it contains class instances, you need to build new instances of that class, or they will be referenced

Sometimes it's easier to just do it yourself; see if you get some ideas from this:

using System; using System.Collections.Generic; namespace YourNameSpace { public class Student { public List<int> Scores; public Student CloneOf; public Student(string name, params int[] scores) { CloneOf = null; Name = name; Scores = new List<int>(scores); } public string Name { get; set; } public bool AddScore(int score) { try { Scores.Add(score); } catch { return false; } return true; } public List<int> GetScores() { return Scores; } public int GetScoreAt(int index) { return (int)Scores[index]; } public int GetScoreTotal() { int sum = 0; foreach (int score in Scores) { sum += score; } return sum; } public int GetScoreCount() { return Scores.Count; } public int GetScoreAverage() { return GetScoreTotal() / GetScoreCount(); } public void DestroyScores() { Scores = new List<int>(); } } public static class StudentExtensions { public static Student Clone(this Student stdnt) { var clone = new Student ( stdnt.Name, stdnt.Scores.ToArray() ) // note use of object initializer here { CloneOf = stdnt }; return clone; } public static void SaveEdits(this Student stdnt, Student clone) { if (clone == null || clone.CloneOf == null || clone.CloneOf != stdnt) { throw new ArgumentException("Invalid clone argument"); } if (stdnt.Scores != clone.Scores) stdnt.Scores = clone.Scores; if (stdnt.Name != clone.Name) stdnt.Name = clone.Name; // consider disposing of clone here ? } } }

Usage example:

Student s1 = new Student("S1", 89,92,100,78); Student s2 = s1.Clone(); s2.Scores[2] = 87; s1.SaveEdits(s2);

更多推荐

如何在C#中使用icloneable接口

本文发布于:2023-06-10 18:30:29,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/616415.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:接口   如何在   icloneable

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!