1. 程式人生 > >C#中完美克隆引用型別的物件

C#中完美克隆引用型別的物件

我們都知道,在C#中,對於複雜物件,每宣告一個牸型別的變數a,並用個該型別的物件A給這個變數賦值的時候,其實是讓這個變數a指向了物件A,在記憶體中並沒有多生成一個物件A的例項.所以不管我們宣告多少個等於A的變數,其實際上永遠都只有一個A存在於記憶體中.這就是我們常說的引用型別的特性.

引用型別的這一特性的好處是不言無喻的,然而,它也給我們帶了一小點不便,那就是有時候,偶爾我們需要在記憶體中有兩個所有屬性值都一模一樣的物件A和B,這樣便於對B做操作而不影響到A.有人說那New兩次不就有兩個一模一樣的物件了嗎,其實,他沒有考慮到在實際的操作過程中,物件A可能因為使用者的操作,一些屬性被改變了.New出來的物件只能確保初始狀態型別和屬性的一致性,對於執行時改變的屬性它就無能為力了.也就是說,此時,我們得克隆一個A物件,把當前A物件的所有屬性值取到新物件中去,這樣就能保證當前兩個物件的一致性.看程式碼吧:

/// 
/// 克隆一個物件
/// /// /// private object CloneObject(object o) { Type t =o.GetType(); PropertyInfo[] properties =t.GetProperties(); Object p =t.InvokeMember("", System.Reflection.BindingFlags.CreateInstance, null, o, null); foreach(PropertyInfo pi in properties) { if(pi.CanWrite) { object
value=pi.GetValue(o, null); pi.SetValue(p, value, null); } } return p; }
呼叫程式碼生成新的一模一樣的物件就很方便了,示例:
TextBox t =(TextBox)CloneObject(textBox1);
當然,在實際使用的過程中,我發現上面的方法也是有缺陷的,比如在克隆DataGridView物件的時候,SetValue的時候會報錯,其中的原因還有待分析.不過我們還有更專業的克隆DataGridView的方法:
/// 
/// 專門克隆DataGridView的方法
/// /// /// public static DataGridView CloneDataGridView(DataGridView dgv) { try { DataGridView ResultDGV = new DataGridView(); ResultDGV.ColumnHeadersDefaultCellStyle = dgv.ColumnHeadersDefaultCellStyle.Clone(); DataGridViewCellStyle dtgvdcs = dgv.RowsDefaultCellStyle.Clone(); dtgvdcs.BackColor = dgv.DefaultCellStyle.BackColor; dtgvdcs.ForeColor = dgv.DefaultCellStyle.ForeColor; dtgvdcs.Font = dgv.DefaultCellStyle.Font; ResultDGV.RowsDefaultCellStyle = dtgvdcs; ResultDGV.AlternatingRowsDefaultCellStyle = dgv.AlternatingRowsDefaultCellStyle.Clone(); for (int i = 0; i < dgv.Columns.Count; i++) { DataGridViewColumn DTGVC = dgv.Columns[i].Clone() as DataGridViewColumn; DTGVC.DisplayIndex = dgv.Columns[i].DisplayIndex; if (DTGVC.CellType == null) { DTGVC.CellTemplate = new DataGridViewTextBoxCell(); ResultDGV.Columns.Add(DTGVC); } else { ResultDGV.Columns.Add(DTGVC); } } foreach (DataGridViewRow var in dgv.Rows) { DataGridViewRow Dtgvr = var.Clone() as DataGridViewRow; Dtgvr.DefaultCellStyle = var.DefaultCellStyle.Clone(); for (int i = 0; i < var.Cells.Count; i++) { Dtgvr.Cells[i].Value = var.Cells[i].Value; } if (var.Index % 2 == 0) Dtgvr.DefaultCellStyle.BackColor = ResultDGV.RowsDefaultCellStyle.BackColor; ResultDGV.Rows.Add(Dtgvr); } return ResultDGV; } catch (Exception ex) { MessageBox.Show(ex.Message); } return null; }

現在就沒有遺憾了.

相關推薦

C#完美克隆引用型別物件

我們都知道,在C#中,對於複雜物件,每宣告一個牸型別的變數a,並用個該型別的物件A給這個變數賦值的時候,其實是讓這個變數a指向了物件A,在記憶體中並沒有多生成一個物件A的例項.所以不管我們宣告多少個等於A的變數,其實際上永遠都只有一個A存在於記憶體中.這就是我們常說的引用型別

c++的常量,常物件,常引用,常指標

   所謂常量是指在程式執行中值始終不可改變的量。而常物件是指他的資料成員在物件的整個生存週期內不能改變。這也意味著不能用常物件去呼叫普通的成員函式,因為有可能會改變常物件的資料成員,所以便有了常成員函式。如果一個物件被宣告為常物件,他只能呼叫常成員函式。普通物件也能呼叫常成員函式

為什麼C++千萬不要返回區域性物件或變數的引用和指標

大家都知道一個常識:“C++中千萬不要返回區域性物件或變數的引用和指標”。 既然所有C++權威的書上都要求“一定不要返回區域性物件或變數的引用和指標”,那為什麼C++編譯器不從語法上直接禁掉這種用法。如果只是建議的話,那麼“返回區域性物件或變數的引用和指標”是否有用武之地

c# 關於office引用釋放 技巧

nbsp add ati cts eas ase tin 技巧 -a 最近使用了powerpoint的相關accemblies, 使用到最後總是不能正確的把PowerPoint進程關閉掉。 網上搜了好久,終於找到一篇文章,詳細介紹了如何使用,以及如何釋放比較安全。

C#系列 ----- 3 值引用物件引用

值型別和引用型別(Value Types Versus Reference Types) 上一篇對於type的定義其實不準確,在此給出更準確的定義。 所有的C#型別包括: Value types Reference types Generic type par

c++什麼是引用,什麼是指標。

引用就是引用地址,給變數取個小名,這個都可以改變變數的數值。 程式碼: #include <iostream>   using namespace std;   int main () {    // 宣告簡單的變數   &n

C++指標和引用的區別、以及引用和取地址符&的區別

一. 指標和引用的區別 對於指標來說,它是一個地址,這個地址是一個數值,那麼就意味這個數值可以為0(空指標),也可以為其他,即指標可以不指向任何東西。 而對於引用來說,他是一個外號,外號一定是“某個存在物體”的外號,所以引用不能為空,即不能存在空引用。例如我們給小明起了個外號:明明,那我們說

C++const與引用,指標之間的關係要點

一、const關鍵字 1、有時我們希望定義這樣的一個變數,它的值不能被改變。這時就可以在定義變數時加上const關鍵字。例如 const int bufSize=512; const型別變數可以進行大部分與非const型別變數相同操作,主要的限制就是不可以在const型別的物件上執

javaScript(其他引用型別物件)

javascript其他引用型別物件 Global物件(全域性)這個物件不存在,無形的物件,無法new一個 其內部定義了一些方法和屬性:如下 encodeURI str = www.baidu.com cn encodeURI(str) encodeURIComp

C++指標和引用還有*和&的關係

*是取值,&是取地址。 在函式定義宣告的時候按照谷歌規範,輸入是const &型別的,輸出是指標型別的。 在使用過程中如果輸入是上一個函式的輸出,在使用的時候需要使用&或者星號×指標進行處理。 在函式宣告過程中使用&表示引用,函式內對引數進行了修改外部也會發生

初夏小談:C++“指標”和“引用“”的區別

1.引用只能繫結一個實體,而指標可以指向不同實體2.使用指標時要判空,而引用不需要因此更安全3.引用在定義時必須初始化,指標不做要求4.在sizeof中:引用結果是引用型別的大小,但指標始終是地址空間所佔位元組個數 void Size() { long long x =

《隨筆十八》—— C++的 “ 標準庫型別string ”

  目錄 初始化 string 物件的方式 string 物件的操作 cin 和 getline  讀寫 string物件 string 的 size ()操作 和  string::size_type 型別 比較string物件

C#程式設計基礎第十課:C#的常用資料型別轉換:隱式轉換、顯式轉換、Convert類轉換等

知識點:型別轉換、數值型別間的轉換、隱式型別轉換、顯式型別轉換、數值型別和string型別的轉換、Convert類轉換。 1、資料型別型別轉換 理解:從根本上說是型別鑄造,或者說是把資料從一種型別轉換為另一種型別。C#有多種資料型別,在使用各種型別的資料時,有時候需要將一種型別的資料轉換

java for迴圈使用克隆代替new物件

public class User implements Cloneable { private Integer age; private String name; pub

C#泛型、引用型別、值型別和Object的效能比較

最近在看C#的泛型,據CLR via C# (第4版)上的說明,泛型是最優的。 對此,先秉持著懷疑的心態的看問題,先驗證一下是否如此。 以下在Main()中實現了個示例,例證的思路是:通過多次執行呼叫,統計並比較不同型別呼叫的時間。 static void M

引用型別----物件和陣列

 1. 建立物件:物件(引用型別的值,是引用型別的一個例項)          建立Object例項。         &

C++4個與型別轉換相關的關鍵字

static_cast const_cast dynamic_cast reinterpret_cast 一.型別轉換     表示式是否合法取決於運算元的型別,而且合法的表示式其含義也由運算元型別決定。在C++中,某些型別之間存在相

C++指標和引用的區別

下面用通俗易懂的話來概述一下: 指標-對於一個型別T,T*就是指向T的指標型別,也即一個T*型別的變數能夠儲存一個T物件的地址,而型別T是可以加一些限定詞的,如const、volatile等等。見下圖,所示指標的含義: 引用-引用是一個物件的別名,主要用於函式引

C#的弱引用

一般情況下例項化一個類或結構時,只要有程式碼引用它,就會形成強引用。 例如: Student stu=new Student();對此,垃圾回收器就不能收集該物件。 一般而言是沒有問題的,因為可能需要訪問stu物件,但是如果物件過大,並且不經常訪問呢?此時就可以建立物件

C++ Traits技術 (4) —— 型別推導

繼續理解traits技術。 當我們處理原生指標時,會遇到需要知道其所指物件型別這樣的問題。如何實現呢? template <class T> void testTypeForward(T t) { // write code here }C++中我們不允許