C# 实现数组深拷贝的一种标准方法

news/2024/7/23 23:54:07 标签: wpf

首先让你的数据类实现接口 ICloneable

比如:

     public class Info : INotifyPropertyChanged, ICloneable
     {

        // 实现ICloneable的Clone函数
        public object Clone()
        {
            return this;  //注意这里返回this
        }
        

        public Info(string time, string name, double score, string result)
        {
            this.Time = time;
            this.Name = name;
            this.Score = score;
            this.Result = result;

        }
        
        
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }

        

        private string time;
        public string Time
        {
            get { return time; }
            set
            {
                time = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Time"));
            }
        }

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Name"));
            }
        }


        private double score;
        public double Score
        {
            get { return score; }
            set
            {
                score = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Score"));
            }
        }



        private string result;
        public string Result
        {
            get { return result; }
            set
            {
                result = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Result"));
            }
        }

    }

那我们的数组就是该数据类的数组,为了让这个深拷贝方法通用,我们使用泛型.

这里我们使用的集合类型是ObservableCollection,你也可以改为List,或者其他类型。

        public static ObservableCollection<T> DeepCopy<T>(IEnumerable<T> list)
            where T : ICloneable
        {
            return new ObservableCollection<T>(list.Select(x => x.Clone()).Cast<T>());          
        }

Select 表示将表中的元素映射到另一张表。Cast表示转换集合中的每个元素的类型。

具体的使用方法如下:

//保留一个备份
infos_copy = DeepCopy<Info>(infos); //其中infos的类型:ObservableCollection<Info>

这样就实现了一个集合的拷贝。

----------------------------------------------------------------------------

还有一个更通用的方法,可以设拷贝任何可序列化的对象

首先我们需要定义个拓展方法,请回顾一下拓展方法的语法。

/// <summary>
/// 对象的深拷贝对象。
/// 注意“T”及其里面的引用类型必须标记为可序列化。
/// </summary>
public static T Copy<T>(this T obj) 
	where T : class
{
	using (var ms = new MemoryStream())
	{
		var bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
		bf.Serialize(ms, obj);
		ms.Seek(0, SeekOrigin.Begin);
		T CloneObject = default(T);

		try
		{
			// 反序列化至另一个对象(即创建了一个原对象的深表副本) 
			CloneObject = (T)bf.Deserialize(ms);
		}
		catch (Exception ex)
		{
			LogHelper.Error("深拷贝对象失败", ex);
		}

		return CloneObject;
	}
}

首先这里用到了this去去修饰一个泛型,而且这个泛型被约束为一个class类型。

也就是说,这个Copy函数几乎是为所以类写的扩展函数. 当然前提是这个类是可序列化的。

如果你需要深拷贝自定义的类,你需要为你的类添加一个[Serializable]标记:

[Serializable]
public class InfoAxisParameter
{
        .....
}

那么使用的时候就十分的方便了:

InfoAxisParameter info = new InfoAxisParameter()
var info_copy = info.Copy()

这里有个小技巧,就是写一个扩展的类TypeExtension,然后将namespace设置为System

这样只要在工程里添加了这个TypeExtension类,那么其他地方无需添加其他的using就能使用这个扩展方法了

namespace System
{
    public static partial class TypeExtension
    {
        /// <summary>
        /// 对象的深拷贝对象。
        /// 注意“T”及其里面的引用类型必须标记为可序列化。
        /// </summary>
        public static T Copy<T>(this T obj) 
            where T : class
        {
            using (var ms = new MemoryStream())
            {
                var bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
                bf.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                T CloneObject = default(T);

                try
                {
                    // 反序列化至另一个对象(即创建了一个原对象的深表副本) 
                    CloneObject = (T)bf.Deserialize(ms);
                }
                catch (Exception ex)
                {
                    LogHelper.Error("深拷贝对象失败", ex);
                }

                return CloneObject;
            }
        }
}


http://www.niftyadmin.cn/n/1734847.html

相关文章

wpf x:Class 前后台逻辑关联的关键!

x:Class"TapeMountingMachine.PageAxisPara1" 表示改Xaml关联的后台逻辑的类名称是PageAxisPara1 如果要修改命令空间的层次&#xff0c;注意这两个地方要同步进行修改~~~

WPF 自定义控件 Loaded 导致的设计器异常 解决方案

设计器异常&#xff0c;提示NullReferenceException 未将对象引用设置到对象例 程序运行时没有问题的&#xff0c; 但是设计器崩了~~ 解决方案&#xff1a; 加上一句话&#xff1a; if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { return; } 问…

C# Func<> 委托

没有参数&#xff1a; Func<TResult> 有参数&#xff1a;Func<T,TResult> T代表传入参数类型&#xff0c;TResult代表返回参数类型&#xff0c;当然可以有多个参数T1、T2、T3… 上代码 class FuncTest{string One(int num, string str, float f){return $"…

C# partial 的使用技巧

partial 可以实现将一个类的类容分布到不同的cs文件. 然后通过文件名&#xff0c;可以达到这种效果~~~~ 这样感觉还是挺酷的~~~

native层 安卓_要成为人工智能时代的安卓?Rokid发布开源AI操作系统YodaOS

移动互联网时代&#xff0c;无论是安卓系统&#xff0c;还是iOS系统都是为以「多点触控」为交互方式的设备做优化和适配&#xff0c;不过随着AI时代的到来&#xff0c;人机交互方式已经悄然发生了变化。人机交互方式的发展趋势为多模态交互&#xff0c;现有操作系统已无法满足&…

WPF 项目中的Properties

Properties为Property的复数形式。 Property&#xff1a;资产&#xff0c;财产&#xff0c;属性&#xff0c;房产&#xff0c;房地产&#xff0c;属性。 每当我们新建一个项目的时候&#xff0c;都包含这个&#xff1a; 那么他呢其实对应了一个文件夹&#xff1a;你可以打开它…

WPF 等宽字体

有时空格的宽度比字母小 想在textbox中字母与空格占用的宽度相同&#xff0c;需要设置&#xff1a; FontFamily"Courier New" 这个是关键 其实&#xff0c;空格格式化&#xff0c;及不够长度用空格代替。 比如&#xff1a;关键使用方法&#xff1a;PadRight in…

resthighlevelclient 工具类_这10个安全测试工具,优秀且免费

有不少开发人员觉得安全测试是最难以实现自动化的部分&#xff0c;其实这主要是由于没有找到合适的工具来进行测试。今天给大家介绍10个易用、开源且免费的安全测试工具&#xff0c;希望能够对你有帮助。1、Nishang如果喜欢用PowerShell&#xff0c;那么可以试试Nishang。Nisha…