程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 按自己的想法去了解事情和泛型(C#)

按自己的想法去了解事情和泛型(C#)

編輯:C#入門知識

按自己的想法去了解事情和泛型(C#)。本站提示廣大學習愛好者:(按自己的想法去了解事情和泛型(C#))文章只能為提供參考,不一定能成為您想要的結果。以下是按自己的想法去了解事情和泛型(C#)正文


上一篇那些年困擾我們的委托(C#)講了委托,這一篇自然就輪到事情了。

不喜歡官方的表達方式,喜歡依照自己的想法去了解一些籠統的東西,我是一個喜歡復雜怕費事的人。

事情

思索到委托運用的一些缺陷,就有了事情。委托是不平安的,打個比如,假如把委托當作共有字段,那麼事情就相當於是屬性的概念。

事情就是被限制運用的委托變量,事情外面封裝了一個多播委托。

事情語法:public event 委托類型 事情名;

事情的作用:事情的作用與委托變量一樣,只是功用上比委托變量有更多的限制。比方:只能經過+=或許-=來綁定辦法。只能在類外部調用事情。

當一個後果發作時,有能夠惹起另外的一些反響,這就仿佛因果關系。而事情則是這個因與果的外部聯絡。

事情的實質:委托的一個實例,添加了event關鍵字修飾。

委托是一品種型,事情是委托類型的實例。

和委托的區別:

  • 事情不能用=來注冊辦法。(避免裡面直接賦值為null,招致注冊生效)
  • 事情不能被內部調用(平安性控制)

整個windows零碎都是經過事情驅動的,事情都有觸發條件。

在WebForm或許WinForm中,我們常常看到:

        private void button1_Click(object sender, EventArgs e)
        {
            //代碼
        }

下面是一個按鈕的單擊事情。從上可以看到三個事情要素:

  • 對象:button
  • 事情名:click
  • 參數:object sender,事情源,在這裡其實就是button,eventArgs e是事情需求的資源數據。

我們在Winform中都是經過如下的方式來注冊事情的。

this.button1.Click += new System.EventHandler(this.button1_Click);

EventHandler就是一個委托:

public delegate void EventHandler(object sender, EventArgs e);

這也就是為什麼我們注冊的事情總是有sender和e這兩個參數,由於委托就是這樣聲明的。我們來自定義一個事情:

        public event EventHandler OnSay;
        public Form1()
        {
            InitializeComponent();
            OnSay += Form1_OnSay;
        }

        void Form1_OnSay(object sender, EventArgs e)
        {
            Console.Write("你好嗎");
        }

我們經過Reflector工具來檢查:

事情OnSay中,其實是2個辦法,我們來看下源碼:

        public void add_OnSay(EventHandler value)
        {
            EventHandler handler2;
            EventHandler onSay = this.OnSay;
            do
            {
                handler2 = onSay;
                EventHandler handler3 = (EventHandler)Delegate.Combine(handler2, value);
                onSay = Interlocked.CompareExchange<EventHandler>(ref this.OnSay, handler3, handler2);
            }
            while (onSay != handler2);
        }
        public void remove_OnSay(EventHandler value)
        {
            EventHandler handler2;
            EventHandler onSay = this.OnSay;
            do
            {
                handler2 = onSay;
                EventHandler handler3 = (EventHandler)Delegate.Remove(handler2, value);
                onSay = Interlocked.CompareExchange<EventHandler>(ref this.OnSay, handler3, handler2);
            }
            while (onSay != handler2);
        }

 這裡可以看出對事情的操作,其實最終還是表現在對委托的操作。

泛型

為什麼要有泛型?

更好的完成代碼復用,但是它不是經過面向對象的思想來完成代碼復用。面向對象習用的三板斧:封裝、承繼、多態。

我們先來看一下代碼,假定在一個類中有多個辦法,他們的操作很相似,能夠僅僅只是傳入的參數類型不同而已

using System;

namespace GenericsDemo
{
    public class MethodTest
    {
        public void IntShow(int i)
        {
            Console.WriteLine(string.Format("IntShow辦法,參數類型{0}",i.GetType()));
        }
        public void StrShow(string s)
        {
            Console.WriteLine(string.Format("StrShow辦法,參數類型{0}", s.GetType()));
        }
    }
}

假如一個類中存在多個這樣的辦法,我們總不能把一切的辦法都這麼寫一遍吧,有沒有一種方式來將這些辦法停止兼並呢?

這個時分我們會想到Object是任何類型的父類,任何父類呈現的中央,都可以運用子類來替代。接上去,我們來改造一下代碼完成:

        public void ObjShow(object obj)
        {
            Console.WriteLine(string.Format("ObjShow辦法,參數類型{0}", obj.GetType()));
        }

我們來看下調用:

            _MethodTest.IntShow(1);
            _MethodTest.StrShow("1");

            _MethodTest.ObjShow(1);
            _MethodTest.ObjShow("1");

辦法是兼並了,但是如今存在什麼樣的問題?呈現了裝箱拆箱,嚴重影響功能。而且不夠平安,由於假如當我把代碼停止如下修正時,會發作什麼

        public void ObjShow(object obj)
        {
            //Console.WriteLine(string.Format("ObjShow辦法,參數類型{0}", obj.GetType()));
            Console.WriteLine(string.Format("ObjShow辦法,參數類型{0},參數值{1}", obj.GetType(),Convert.ToInt32(obj)));
        }

調用代碼:_MethodTest.ObjShow("a");

編譯時不會報錯,但是運轉時就報錯了。也就是說經過object來作為參數傳遞,其實是存在嚴重的平安隱患的。

那麼有沒有什麼方法來處理這兩個問題呢?C#2.0泛型的呈現正是基於這樣的需求。

        public void GenericsShow<T>(T t)
        {
            Console.WriteLine(string.Format("GenericsShow辦法,參數類型{0}", t.GetType()));
        }

調用代碼:_MethodTest.GenericsShow<int>(1);

這樣依賴,泛型辦法在聲明的時分可以完成相似於Objet的效果,在調用時先確定類型,這樣就到達了平安反省的目的。

泛型好像是運用了一個類型占位符,而這一特性在運用集合時更能表現其弱小之處。

也正是由於泛型太弱小了,弱小得像孫悟空一樣,我們需求弄一道緊箍咒來對其停止約束,否則不容易控制。這時,就有了泛型約束,它在泛型辦法或許泛型委托聲明之時就對其停止限定。限定關鍵字經過where。

   public class Student
    {
        public string Name { get; set; }
    }
        public void StudentShow<T>(T t) where T : Student
        {
            Console.WriteLine(string.Format("GenericsShow辦法,參數類型{0}", t.GetType()));
        }
        public void GenericsShow<T>(T t)
        {
            Console.WriteLine(string.Format("GenericsShow辦法,參數類型{0}", t.GetType()));
        }
        public void GenericsShow<T>(T t)
        {
            Console.WriteLine(string.Format("GenericsShow辦法2,參數類型{0}", t.GetType()));
        }

需求留意的是,這裡運用了泛型重載,這個時分編譯是可以正常經過的,可是留意了,調用的時分就呈現問題了

為什麼會這樣呢?由於泛型的類型參數在編譯器並不能確定其類型,而重載時停止類型反省發送在實例辦法被調用時。

同時需求留意的是,當普通辦法和泛型辦法同時調用時,優先選擇普通辦法,由於編譯器會停止類型推斷。

泛型的運用遠不止於此,它還支持泛型承繼、泛型接口、泛型類、泛型委托等。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved