日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

C#Object类型

發布時間:2023/12/29 C# 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C#Object类型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在C#中,Object類型是所有類型的根,大家平常開發中都要跟它打交道,但不見得對它里面的每個方法都知根知底,下面對它里面的每個方法都進行仔細的總結。
概述:
構造函數
Equals函數
Finalize函數
GetHashCode函數
GetType()函數
ReferenceEquals函數
MemberWiseClone()函數
ToString()函數
Object類型中一共有8個方法,重載的方法沒有算進來。下面一一來看看這些方法。
1、構造函數
函數簽名:public Object()
作用:這個就不用多說了
注意點:直接使用new Object()可以用來創建對象;如果非Object類型,則在該類型的構造函數被調用時,該函數自動被調用。
2、Equals函數,該方法有重載函數
函數簽名:public virtual bool Equals(Object obj)
public static bool Equals(Object objA,Object objB)
先來看看public virtual bool Equals(Object obj),從簽名里就可以看出來,這個方法是用來開放給繼承類去根據實際情況重寫的。
注意點:
1)默認情況下,對于引用類型,該方法對比的時引用的地址,對于值類型,對比的是值的二進制描述是否相同。100.0與100雖然都是100,但是它們的二進制分布是不一樣的。
2)不管是引用類型還是值類型,重寫該方法的主要目的都是實現根據值來判斷對象是否相等。
3)該方法本身只支持原子類型的比較以及簡單對象的比較,如果是自定義復雜的類型,則有必要重寫該方法。
4)重寫該方法時,應滿足一些規則。
首先x.Equals(x)應該返回true;
x.Equals(y)的結果應該與y.Equals(x)相同;
x.Equals(y)返回true,如果x和y都是Nan;
如果x.Equals(y) && y.Equals(z),則x.Equals(z)應該返回true;
x.Equals(null)都返回false;
5)在重寫Equals()方法時,不應該拋出異常;
6)實現IComparable接口的話,一定記得重寫Equals方法;
7)如果重寫了Equals(),則一般情況也必須重寫GetHashCode(),不然如果把該類型的對方放在hashtable結構上的話可能產生問題;
8)如果對==進行了操作符重載,則記得一定重寫Equals();按照這樣的設計方法,類型代碼在調用Equals時的運行結果,能夠跟應用程序調用==時的結果保持一致。
看完了public virtual bool Equals(Object obj),我們接著來看看它的重載方法public static bool Equals(Object objA,Object objB)
該方法返回true的條件:
1)objA和objB是同一個實例
2)objA和objB都是null
3)objA.Equas(objB)返回true
注意上面三個條件是||的關系
對比這兩個Equals方法,還是很容易對比出不同點的。
3、Finalize函數
函數簽名:protected virtual void Finalize()
作用:允許對象在垃圾回收回收該對象之前嘗試釋放資源并執行其它清理操作。
注意點:
Finalize 是受保護的,因此只能通過此類或派生類訪問它。
對象變為不可訪問后將自動調用此方法,除非已通過 SuppressFinalize 調用使對象免除了終結。在應用程序域的關閉過程中,對沒有免除終結的對象將自動調用 Finalize,即使那些對象仍是可訪問的。對于給定的實例僅自動調用 Finalize 一次,除非使用 ReRegisterForFinalize 這類機制重新注冊該對象并且后面沒有調用 GC.SuppressFinalize。
派生類型中的每個 Finalize 實現都必須調用其基類型的 Finalize 實現。這是唯一一種允許應用程序代碼調用 Finalize 的情況。
Finalize 操作具有下列限制:
垃圾回收過程中執行終結器的準確時間是不確定的。不保證資源在任何特定的時間都能釋放,除非調用 Close 方法或 Dispose 方法。
即使一個對象引用另一個對象,也不能保證兩個對象的終結器以任何特定的順序運行。即,如果對象 A 具有對對象 B 的引用,并且兩者都有終結器,則當對象 A 的終結器啟動時,對象 B 可能已經終結了。
運行終結器的線程是未指定的。
在下面的異常情況下,Finalize 方法可能不會運行完成或可能根本不運行:
另一個終結器無限期地阻止(進入無限循環,試圖獲取永遠無法獲取的鎖,諸如此類)。由于運行時試圖運行終結器來完成,所以如果一個終結器無限期地阻止,則可能不會調用其他終結器。
進程終止,但不給運行時提供清理的機會。在這種情況下,運行時的第一個進程終止通知是 DLL_PROCESS_DETACH 通知。
在關閉過程中,只有當可終結對象的數目繼續減少時,運行時才繼續 Finalize 對象。
如果 Finalize 或 Finalize 的重寫引發異常,并且運行庫并非寄宿在重寫默認策略的應用程序中,則運行庫將終止進程,并且不執行任何活動的 try-finally 塊或終結器。如果終結器無法釋放或銷毀資源,此行為可以確保進程完整性。
對實現者的說明:
默認情況下,Object..::.Finalize 不執行任何操作。只有在必要時才必須由派生類重寫它,因為如果必須運行 Finalize 操作,垃圾回收過程中的回收往往需要長得多的時間。
如果 Object 保存了對任何資源的引用,則 Finalize 必須由派生類重寫,以便在垃圾回收過程中,在放棄 Object 之前釋放這些資源。
當類型使用文件句柄或數據庫連接這類在回收使用托管對象時必須釋放的非托管資源時,該類型必須實現 Finalize。有關輔助和具有更多控制的資源處置方式,請參見 IDisposable 接口。
Finalize 可以采取任何操作,包括在垃圾回收過程中清理了對象后使對象復活(即,使對象再次可訪問)。但是,對象只能復活一次;在垃圾回收過程中,不能對復活對象調用 Finalize。
析構函數是執行清理操作的 C# 機制。析構函數提供了適當的保護措施,如自動調用基類型的析構函數。
4、GetHashCode函數
函數簽名:public virtual int GetHashCode()
作用:用作特定類型的哈希函數。
注意點:
GetHashCode 方法適用于哈希算法和諸如哈希表之類的數據結構。
GetHashCode 方法的默認實現不保證針對不同的對象返回唯一值。而且,.NET Framework 不保證 GetHashCode 方法的默認實現以及它所返回的值在不同版本的 .NET Framework 中是相同的。因此,在進行哈希運算時,該方法的默認實現不得用作唯一對象標識符。
GetHashCode 方法可以由派生類型重寫。值類型必須重寫此方法,以提供適合該類型的哈希函數和在哈希表中提供有用的分布。為了獲得最佳結果,哈希代碼必須基于實例字段或屬性(而非靜態字段或屬性)的值。
用作 Hashtable 對象中鍵的對象還必須重寫 GetHashCode 方法,因為這些對象必須生成其各自的哈希代碼。如果用作鍵的對象不提供 GetHashCode 的有用實現,您可以在構造 Hashtable 對象時指定哈希代碼提供程序。在 .NET Framework 2.0 版之前,哈希代碼提供程序是基于 System.Collections..::.IHashCodeProvider 接口的。從 2.0 版開始,哈希代碼提供程序基于 System.Collections..::.IEqualityComparer 接口。
對實現者的說明:
哈希函數用于快速生成一個與對象的值相對應的數字(哈希代碼)。哈希函數通常是特定于每個 Type 的,而且,必須至少使用一個實例字段作為輸入。
哈希函數必須具有以下特點:
如果兩個對象的比較結果相等,則每個對象的 GetHashCode 方法都必須返回同一個值。但是,如果兩個對象的比較結果不相等,則這兩個對象的 GetHashCode 方法不一定返回不同的值。
一個對象的 GetHashCode 方法必須總是返回同一個哈希代碼,但前提是沒有修改過對象狀態,對象狀態用來確定對象的 Equals 方法的返回值。請注意,這僅適用于應用程序的當前執行,再次運行該應用程序時可能會返回另一個哈希代碼。
為了獲得最佳性能,哈希函數必須為所有輸入生成隨機分布。
例如,String 類提供的 GetHashCode 方法的實現為相同的字符串值返回相同的哈希代碼。因此,如果兩個 String 對象表示相同的字符串值,則它們返回相同的哈希代碼。另外,該方法使用字符串中的所有字符生成相當隨機的分布式輸出,即使當輸入集中在某些范圍內時(例如,許多用戶可能有只包含低位 128 個 ASCII 字符的字符串,即使字符串可以包含 65,535 個 Unicode 字符中的任何字符)。
對于 Object 的派生類,當且僅當此派生類將值相等性定義為引用相等并且類型不是值類型時,GetHashCode 方法才可以委托給 Object..::.GetHashCode 實現。
在類上提供好的哈希函數可以顯著影響將這些對象添加到哈希表的性能。在具有好的哈希函數實現的哈希表中,搜索元素所用的時間是固定的(例如運算復雜度為 O(1) 的運算)。而在具有不好的哈希函數實現的哈希表中,搜索性能取決于哈希表中的項數(例如運算復雜度為 O(n) 的運算,其中的 n 是哈希表中的項數)。哈希函數的計算成本也必須不高。
GetHashCode 方法的實現必須不會導致循環引用。例如,如果 ClassA.GetHashCode 調用 ClassB.GetHashCode,ClassB.GetHashCode 必須不直接或間接調用 ClassA.GetHashCode。
GetHashCode 方法的實現必須不引發異常。
重寫 GetHashCode 的派生類還必須重寫 Equals,以保證被視為相等的兩個對象具有相同的哈希代碼;否則,Hashtable 類型可能無法正常工作。
示例
在某些情況下,GetHashCode 方法的實現只返回整數值。下面的代碼示例闡釋了返回整數值的 GetHashCode 的實現。
using System;
public struct Int32 {
public int value;
//other methods…
public override int GetHashCode()
{
return value;
}
}
一個類型常具有多個可以參與生成哈希代碼的數據字段。生成哈希代碼的一種方法是使用 XOR (eXclusive OR) 運算合并這些字段,如下面的代碼示例所示。
using System;
public struct Point {
public int x;
public int y;
//other methods
public override int GetHashCode() {
return x ^ y;
}
}
下面的代碼示例闡釋了另一種情況:使用 XOR (eXclusive OR) 合并該類型的字段以生成哈希代碼。注意,在該代碼示例中,字段表示用戶定義的類型,每個類型都實現 GetHashCode 和 Equals。
using System;
public class SomeType {
public override int GetHashCode() {
return 0;
}
}
public class AnotherType {
public override int GetHashCode() {
return 1;
}
}
public class LastType {
public override int GetHashCode() {
return 2;
}
}
public class MyClass {
SomeType a = new SomeType();
AnotherType b = new AnotherType();
LastType c = new LastType();
public override int GetHashCode () {
return a.GetHashCode() ^ b.GetHashCode() ^ c.GetHashCode();
}
}
如果派生類的數據成員比 Int32 大,則可以使用 XOR (eXclusive OR) 運算合并該值的高序位和低序位,如下面的代碼示例所示。
using System;
public struct Int64 {
public long value;
//other methods…
public override int GetHashCode() {
return ((int)value ^ (int)(value >> 32));
}
}
5、GetType()函數
函數簽名:public Type GetType()
作用:獲取當前實例的確切運行時類型。
注意點:
對于具有相同運行時類型的兩個對象 x 和 y,雖然Object.ReferenceEquals(x,y)返回的是false,但是 Object.ReferenceEquals(x.GetType(),y.GetType()) 返回 true。
Type 對象公開與當前 Object 的類關聯的元數據。
下面的代碼示例說明 GetType 返回當前實例的運行時類型。
using System;
public class MyBaseClass: Object {
}
public class MyDerivedClass: MyBaseClass {
}
public class Test {
public static void Main() {
MyBaseClass myBase = new MyBaseClass();
MyDerivedClass myDerived = new MyDerivedClass();
object o = myDerived;
MyBaseClass b = myDerived;
Console.WriteLine(“mybase: Type is {0}”, myBase.GetType());
Console.WriteLine(“myDerived: Type is {0}”, myDerived.GetType());
Console.WriteLine(“object o = myDerived: Type is {0}”, o.GetType());
Console.WriteLine(“MyBaseClass b = myDerived: Type is {0}”, b.GetType());
}
}
6、ReferenceEquals函數
函數原型:public static bool ReferenceEquals( Object objA,Object objB )
作用:判斷兩個指定的對象實例是否是同一個實例。從描述也可以看出來,如果參數是值類型,則會裝箱,比較的是裝箱后的對象實例。
注意:
如果 objA 是與 objB 是相同的實例,或者如果二者都為空引用,則為 true;否則為 false。
下面的代碼示例使用 ReferenceEquals 確定兩個對象是否是相同的實例。
using System;
class MyClass {
static void Main() {
object o = null;
object p = null;
object q = new Object();
Console.WriteLine(Object.ReferenceEquals(o, p));
p = q;
Console.WriteLine(Object.ReferenceEquals(p, q));
Console.WriteLine(Object.ReferenceEquals(o, p));
}
}
7、MemberWiseClone()函數
函數簽名:protected Object MemberWiseClone()
作用:創建當前 Object 的淺表副本。
注意:
MemberwiseClone 方法創建一個淺表副本,方法是創建一個新對象,然后將當前對象的非靜態字段復制到該新對象。如果字段是值類型的,則對該字段執行逐位復制。如果字段是引用類型,則復制引用但不復制引用的對象;因此,原始對象及其復本引用同一對象。非靜態字段屬于整個類,不管是深拷貝,還是淺拷貝,都是不需要處理的。并且需要注意該方法是protected的,即只有在類本身內部,或者它的繼承者內部才能夠調用它。
例如,考慮一個名為 X 的對象,該對象引用對象 A 和 B。對象 B 又引用對象 C。X 的淺表副本創建一個新對象 X2,該對象也引用對象 A 和 B。與此相對照,X 的深層副本創建一個新對象 X2,該對象引用新對象 A2 和 B2,它們分別是 A 和 B 的副本。B2 又引用新對象 C2,C2 是 C 的副本。使用實現 ICloneable 接口的類執行對象的淺表或深層復制。
下面的代碼示例說明如何使用 MemberwiseClone 復制類的實例。
using System;
class MyBaseClass {
public static string CompanyName = “My Company”;
public int age;
public string name;
}
class MyDerivedClass: MyBaseClass {
static void Main() {
// Creates an instance of MyDerivedClass and assign values to its fields.
MyDerivedClass m1 = new MyDerivedClass();
m1.age = 42;
m1.name = “Sam”;
// Performs a shallow copy of m1 and assign it to m2.
MyDerivedClass m2 = (MyDerivedClass) m1.MemberwiseClone();
}
}
8、ToString()函數
函數簽名:public virtual string ToString()
作用:返回一個代表當前對象的字符串
注意:默認情況下返回的是該對象所屬類型的全名稱。繼承類可以重寫該方法,以便自定義顯示輸出內容,如果繼承類需要控制更多的格式化輸出,則需要實現IFormattable接口。
下面的代碼演示了如何重寫ToString(),以及如何實現IFormattable接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IFormattablePractise
{
public class Point : IFormattable
{
int x;
int y;
public Point(int x , int y)
{
this.x = x;
this.y = y;
}
public override string ToString()
{
return ToString(null, null);
}

region IFormattable Members

public string ToString(string format, IFormatProvider formatProvider)
{
// If no format is passed, display like this: (x, y).
if (format == null) return String.Format(“({0}, {1})”, x, y);
// For “x” formatting, return just the x value as a string
if (format == “x”) return x.ToString();
// For “y” formatting, return just the y value as a string
if (format == “y”) return y.ToString();
// For any unrecognized format, throw an exception.
throw new FormatException(String.Format(“Invalid format string: ‘{0}’.”, format));
}

endregion

}
class Program
{
static void Main(string[] args)
{
// Create the object.
Point p = new Point(5, 98);
// Test ToString with no formatting.
Console.WriteLine(“This is my point: ” + p.ToString());
// Use custom formatting style “x”
Console.WriteLine(“The point’s x value is {0:x}”, p);
// Use custom formatting style “y”
Console.WriteLine(“The point’s y value is {0:y}”, p);
Console.WriteLine(“my custom point value is ({0:x}:{1:y})”,p,p);
try
{
// Use an invalid format; FormatException should be thrown here.
Console.WriteLine(“Invalid way to format a point: {0:XYZ}”, p);
}
catch (FormatException e)
{
Console.WriteLine(“The last line could not be displayed: {0}”, e.Message);
}
Console.ReadLine();
}
}
}

轉自:http://blog.csdn.net/wnln25/article/details/6678357
C#中的object類深入理解
C#中所有的類都直接或間接繼承自System.Object類,這使得C#中的類得以單根繼承。如果我們沒有明確指定繼承類,編譯器缺省認為該類繼承自System.Object類。System.Object類也可用小寫的object關鍵字表示,兩者完全等同。自然C#中所有的類都繼承了System.Object類的公共接口,剖析它們對我們理解并掌握C#中類的行為非常重要。下面是僅用接口形式表示的System.Object類:

namespace System
{
public class Object
{
public static bool Equals(object objA,object objB){}
public static bool ReferenceEquals(object objA,object objB){}

public Object(){}public virtual bool Equals(object obj){}public virtual int GetHashCode(){}public Type GetType(){}public virtual string ToString(){}protected virtual void Finalize(){}protected object MemberwiseClone(){} }

我們先看object的兩個靜態方法Equals(object objA,object objB),ReferenceEquals(object objA,object objB)和一個實例方法Equals(object obj)。在我們闡述這兩個方法之前我們首先要清楚面向對象編程兩個重要的相等概念:值相等和引用相等。值相等的意思是它們的數據成員按內存位分別相等。引用相等則是指它們指向同一個內存地址,或者說它們的對象句柄相等。引用相等必然推出值相等。對于值類型關系等號“==”判斷兩者是否值相等(結構類型和枚舉類型沒有定義關系等號“==”,我們必須自己定義)。對于引用類型關系等號“==”判斷兩者是否引用相等。值類型在C#里通常沒有引用相等的表示,只有在非托管編程中采用取地址符“&”來間接判斷二者的地址是否相等。

靜態方法Equals(object objA,object objB)首先檢查兩個對象objA和objB是否都為null,如果是則返回true,否則進行objA.Equals(objB)調用并返回其值。問題歸結到實例方法Equals(object obj)。該方法缺省的實現其實就是{return this= =obj;}也就是判斷兩個對象是否引用相等。但我們注意到該方法是一個虛方法,C#推薦我們重寫此方法來判斷兩個對象是否值相等。實際上Microsoft.NET框架類庫內提供的許多類型都重寫了該方法,如:System.String(string),System.Int32(int)等,但也有些類型并沒有重寫該方法如:System.Array等,我們在使用時一定要注意。對于引用類型,如果沒有重寫實例方法Equals(object obj),我們對它的調用相當于this= =obj,即引用相等判斷。所有的值類型(隱含繼承自System.ValueType類)都重寫了實例方法Equals(object obj)來判斷是否值相等。

注意對于對象x,x.Equals(null)返回false,這里x顯然不能為null(否則不能完成Equals()調用,系統拋出空引用錯誤)。從這里我們也可看出設計靜態方法Equals(object objA,object objB)的原因了–如果兩個對象objA和objB都可能為null,我們便只能用object. Equals(object objA,object objB)來判斷它們是否值相等了–當然如果我們沒有改寫實例方法Equals(object obj),我們得到的仍是引用相等的結果。我們可以實現接口IComparable來強制改寫實例方法Equals(object obj)。

對于值類型,實例方法Equals(object obj)應該和關系等號“==”的返回值一致,也就是說如果我們重寫了實例方法Equals(object obj),我們也應該重載或定義關系等號“==”操作符,反之亦然。雖然值類型(繼承自System.ValueType類)都重寫了實例方法Equals(object obj),但C#推薦我們重寫自己的值類型的實例方法Equals(object obj),因為系統的System.ValueType類重寫的很低效。對于引用類型我們應該重寫實例方法Equals(object obj)來表達值相等,一般不應該重載關系等號“==”操作符,因為它的缺省語義是判斷引用相等。

靜態方法ReferenceEquals(object objA,object objB)判斷兩個對象是否引用相等。如果兩個對象為引用類型,那么它的語義和沒有重載的關系等號“==”操作符相同。如果兩個對象為值類型,那么它的返回值一定是false。

實例方法GetHashCode()為相應的類型提供哈希(hash)碼值,應用于哈希算法或哈希表中。需要注意的是如果我們重寫了某類型的實例方法Equals(object obj),我們也應該重寫實例方法GetHashCode()–這理所應當,兩個對象的值相等,它們的哈希碼也應該相等。下面的代碼是對前面幾個方法的一個很好的示例:

using System;
struct A
{
public int count;
}
class B
{
public int number;
}
class C
{
public int integer=0;
public override bool Equals(object obj)
{
C c=obj as C;
if (c!=null)
return this.integer==c.integer;
else
return false;
}
public override int GetHashCode()
{
return 2^integer;
}
}
class Test
{
public static void Main()
{
A a1,a2;
a1.count=10;
a2=a1;

//Console.Write(a1==a2);沒有定義“==”操作符Console.Write(a1.Equals(a2));//True

Console.WriteLine(object.ReferenceEquals(a1,a2));//False

B b1=new B();B b2=new B();b1.number=10;b2.number=10;Console.Write(b1==b2);//FalseConsole.Write(b1.Equals(b2));//False

Console.WriteLine(object.ReferenceEquals(b1,b2));//False

b2=b1;Console.Write(b1==b2);//TrueConsole.Write(b1.Equals(b2));//TrueConsole.WriteLine(object.ReferenceEquals(b1,b2));//TrueC c1=new C();C c2=new C();c1.integer=10;c2.integer=10;Console.Write(c1==c2);//FalseConsole.Write(c1.Equals(c2));//True

Console.WriteLine(object.ReferenceEquals(c1,c2));//False

c2=c1;Console.Write(c1==c2);//TrueConsole.Write(c1.Equals(c2));//TrueConsole.WriteLine(object.ReferenceEquals(c1,c2));//True }

}

如我們所期望,編譯程序并運行我們會得到以下輸出:

True False
False False False
True True True
False True False
True True True

實例方法GetType()與typeof的語義相同,它們都通過查詢對象的元數據來確定對象的運行時類型,我們在“第十講 特征與映射”對此作詳細的闡述。

實例方法ToString()返回對象的字符串表達形式。如果我們沒有重寫該方法,系統一般將類型名作為字符串返回。

受保護的Finalize()方法在C#中有特殊的語義,我們將在“第五講 構造器與析構器”里詳細闡述。

受保護的MemberwiseClone()方法返回目前對象的一個“影子拷貝”,該方法不能被子類重寫。“影子拷貝”僅僅是對象的一份按位拷貝,其含義是對對象內的值類型變量進行賦值拷貝,對其內的引用類型變量進行句柄拷貝,也就是拷貝后的引用變量將持有對同一塊內存的引用。相對于“影子拷貝”的是深度拷貝,它對引用類型的變量進行的是值復制,而非句柄復制。例如X是一個含有對象A,B引用的對象,而對象A又含有對象M的引用。Y是X的一個“影子拷貝”。那么Y將擁有同樣的A,B的引用。但對于X的一個“深度拷貝”Z來說,它將擁有對象C和D的引用,以及一個間接的對象N的引用,其中C是A的一份拷貝,D是B的一份拷貝,N是M的一份拷貝。深度拷貝在C#里通過實現ICloneable接口(提供Clone()方法)來完成。

轉自:http://apps.hi.baidu.com/share/detail/14180240
C# 中object sender與EventArgs e
一、了解C#中的預定義事件處理機制
在寫代碼前我們先來熟悉.net框架中和事件有關的類和委托,了解C#中預定義事件的處理。
EventArgs是包含事件數據的類的基類,用于傳遞事件的細節。
EventHandler是一個委托聲明如下
public delegate void EventHandler( object sender , EventArgs e )
注意這里的參數,前者是一個對象(其實這里傳遞的是對象的引用,如果是button1的click事件則sender就是button1),后面是包含事件數據的類的基類。
下面我們研究一下Button類看看其中的事件聲明(使用WinCV工具查看),以Click事件為例。
public event EventHandler Click;
這里定義了一個EventHandler類型的事件Click
前面的內容都是C#在類庫中已經為我們定義好了的。下面我們來看編程時產生的代碼。
private void button1_Click(object sender, System.EventArgs e)
{

}
這是我們和button1_click事件所對應的方法。注意方法的參數符合委托中的簽名(既參數列表)。那我們怎么把這個方法和事件聯系起來呢,請看下面的代碼。
this.button1.Click += new System.EventHandler(this.button1_Click);
把this.button1_Click方法綁定到this.button1.Click事件。
下面我們研究一下C#事件處理的工作流程,首先系統會在為我們創建一個在后臺監聽事件的對象(如果是 button1的事件那么監聽事件的就是button1),這個對象用來產生事件,如果有某個用戶事件發生則產生對應的應用程序事件,然后執行訂閱了事件的所有方法。
二、簡單的自定義事件(1)
首先我們需要定義一個類來監聽客戶端事件,這里我們監聽鍵盤的輸入。
定義一個委托。
public delegate void UserRequest(object sender,EventArgs e);
前面的object用來傳遞事件的發生者,后面的EventArgs用來傳遞事件的細節,現在暫時沒什么用處,一會后面的例子中將使用。
下面定義一個此委托類型類型的事件
public event UserRequest OnUserRequest;
下面我們來做一個死循環
public void Run() { bool finished=false; do { if (Console.ReadLine()==”h”) { OnUserRequest(this,new EventArgs()); } }while(!finished); }
此代碼不斷的要求用戶輸入字符,如果輸入的結果是h,則觸發OnUserRequest事件,事件的觸發者是本身(this),事件細節無(沒有傳遞任何參數的EventArgs實例)。我們給這個類取名為UserInputMonitor。
下面我們要做的是定義客戶端的類 首先得實例化UserInputMonitor類
UserInputMonitor monitor=new UserInputMonitor();
然后我們定義一個方法。
private void ShowMessage(object sender,EventArgs e)
{
Console.WriteLine(“HaHa!!”);
}
最后要做的是把這個方法和事件聯系起來(訂閱事件),我們把它寫到庫戶端類的構造函數里。
Client(UserInputMonitor m)
{
m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage);
//m.OnUserRequest+=new m.UserRequest(this.ShowMessage);
//注意這種寫法是錯誤的,因為委托是靜態的

}下面創建客戶端的實例。new Client(monitor);對了,別忘了讓monitor開始監聽事件。monitor.run();大功告成,代碼如下:

using System; class UserInputMonitor { public delegate void UserRequest(object sender,EventArgs e); //定義委托 public event UserRequest OnUserRequest; //此委托類型類型的事件 public void Run() { bool finished=false; do { if (Console.ReadLine()==”h”) { OnUserRequest(this,new EventArgs()); } }while(!finished); } }
public class Client { public static void Main() { UserInputMonitor monitor=new UserInputMonitor(); new Client(monitor); monitor.Run(); } private void ShowMessage(object sender,EventArgs e) { Console.WriteLine(“HaHa!!”); } Client(UserInputMonitor m) { m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage); //m.OnUserRequest+=new m.UserRequest(this.ShowMessage); //注意這種寫法是錯誤的,因為委托是靜態的 } }
三、進一步研究C#中的預定義事件處理機制
可能大家發現在C#中有些事件和前面的似乎不太一樣。例如
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e)
{

}this.textBox1.KeyPress+=newSystem.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);這里使用了KeyPressEventArgs而不是EventArgs作為參數。這里使用了KeyEventHandler委托,而不是EventHandler委托。 KeyPressEventArgs是EventArgs的派生類,而KeyEventHandler的聲明如下public delegate void KeyEventHandler( object sender , KeyEventArgs e ); 是參數為KeyEventArgs的委托。那為什么KeyPress事件要這么做呢,我們可以從兩個類的構造函數來找答案。public EventArgs();public KeyPressEventArgs(char keyChar);這里的keyData是什么,是用來傳遞我們按下了哪個鍵的,哈。我在KeyEventArgs中又發現了屬性public char KeyChar { get; }進一步證明了我的理論。下面我們來做一個類似的例子來幫助理解。

四、簡單的自定義事件(2)
拿我們上面做的例子來改。
我們也定義一個EventArgs(類似KeyEventArgs)取名MyEventArgs,定義一個構造函數public MyEventArgs(char keyChar),同樣我們也設置相應的屬性。代碼如下
using System; class MyMyEventArgs:EventArgs { private char keyChar; public MyMyEventArgs(char keyChar) { this.keychar=keychar; } public char KeyChar { get { return keyChar; } } }
因為現在要監聽多個鍵了,我們得改寫監聽器的類中的do…while部分。改寫委托,改寫客戶端傳遞的參數。好了最終代碼如下,好累
using System; class MyEventArgs:EventArgs { private char keyChar; public MyEventArgs(char keyChar) { this.keyChar=keyChar; } public char KeyChar { get { return keyChar; } } }
class UserInputMonitor { public delegate void UserRequest(object sender,MyEventArgs e); //定義委托 public event UserRequest OnUserRequest; //此委托類型類型的事件 public void Run() { bool finished=false; do { string inputString= Console.ReadLine(); if (inputString!=”“) OnUserRequest(this,new MyEventArgs(inputString[0])); }while(!finished); } }
public class Client { public static void Main() { UserInputMonitor monitor=new UserInputMonitor(); new Client(monitor); monitor.Run(); } private void ShowMessage(object sender,MyEventArgs e) { Console.WriteLine(“捕捉到:{0}”,e.KeyChar); } Client(UserInputMonitor m) { m.OnUserRequest+=new UserInputMonitor.UserRequest(this.ShowMessage); //m.OnUserRequest+=new m.UserRequest(this.ShowMessage); //注意這種寫法是錯誤的,因為委托是靜態的 } }

總結

以上是生活随笔為你收集整理的C#Object类型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日韩一级伦理片 | 九色视频在线播放 | 卡一卡二视频 | 天天看天天摸 | 成人在线观看亚洲 | 99久久婷婷国产一区二区三区 | 日本成人社区 | 国产精品自在线 | 国产精品一品二品 | 国产色啪 | 欧美性受xxxxxx黑人xyx性爽 | 婷婷色网站| 国产精品第1页 | 在线观看免费黄视频 | 外国电影免费观看高清完整版 | 黄色aa毛片 | 一级二级三级黄色片 | 夜色一区 | 日韩h在线 | 国产精品一区二区三区在线免费观看 | 午夜美女福利 | 高跟肉丝丝袜呻吟啪啪网站av | 亚洲婷婷在线视频 | 黄色中文字幕 | 嫩草导航| 欧美美女性高潮 | 岛国大片在线免费观看 | 中文在线www | 日韩一区二区免费视频 | 久久久资源| 久久9精品区-无套内射无码 | 国产色视频一区二区三区qq号 | 粉嫩av一区二区 | 国产黄色大片在线观看 | 亚欧洲精品视频 | 91爱| 国产真实乱人偷精品 | 午夜骚影| 超碰国产一区二区三区 | 国产精品无码av在线播放 | 日韩精品1 | 日韩极品在线观看 | 天天色av | 婷婷丁香六月 | 人人做人人爱人人爽 | 动漫av网站免费观看 | 伊人加勒比 | 夜夜骑夜夜骑 | 日批av | 视频在线一区 | 95精品视频| jizzjizz日本人| 精品动漫一区二区三区的观看方式 | 日韩精品一区二区av | 可以免费看的av | 久久久精品人妻一区二区三区四 | 51精产品一区一区三区 | 成人免费看片又大又黄 | 久久精品视频在线播放 | 免费啪视频在线观看 | 麻豆精品网站 | 玉女心经是什么意思 | 亚洲视频自拍偷拍 | 青娱乐在线视频免费观看 | 穿情趣内衣被c到高潮视频 欧美性猛交xxxx黑人猛交 | 国产欧美一区二区三区在线老狼 | 中文日韩字幕 | 琪琪午夜伦理影院7777 | 樱花影院最新免费观看攻略 | 日本五十路在线 | 四虎永久在线观看 | 黑丝美女啪啪 | 国产电影免费观看高清完整版视频 | 国产又粗又猛又爽又黄91 | 碧蓝之海动漫在线观看免费高清 | 久久免费看 | 日韩精品1 | 操她视频网站 | 日韩三级一区二区三区 | 神马午夜av | aaaaa级少妇高潮大片免费看 | 亚洲视频一二三四 | 亚洲第一页在线 | 色综合久久88色综合天天免费 | 丝袜视频在线 | 毛片黄片免费看 | 久久久网站 | 日韩 在线 | 人人爱人人看 | 成为性瘾网黄的yy对象后 | 中文字幕在线1 | 欧美性受xxxx | 亚洲乱色 | 老司机综合网 | 在线久草 | 成人在线视频一区 | 精品久久久久久久久久久久久久久久久久 | 天天干天天插天天操 | 午夜理伦三级做爰电影 |