c#中泛型的解析

                   c#泛型入門簡介

在c#中,我們通常用泛型來處理某個類或方法。比如某個方法要實現某個功能,但 參數的類型不同,我們可以採用重載方法來實現,但這個方法就要重複定義很多遍,所以爲了高效,我們可以採用泛型。

1 泛型方法
首先來看一下不用泛型來實現某個功能

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    /// <summary>
    /// 普通方法
    /// </summary>
    public class CommonMethod
    {
        /// <summary>
        /// int類型參數   
        /// 參數類型是寫死的
        /// </summary>
        /// <param name="iParameter"></param>
        public static void ShowInt(int iParameter)
        {
            Console.WriteLine("This is ShowInt, parameter={0} type={1}", iParameter, iParameter.GetType());
        }
        /// <summary>
        /// string類型參數
        /// </summary>
        /// <param name="sParameter"></param>
        public static void ShowString(string sParameter)
        {
            Console.WriteLine("This is ShowString, parameter={0} type={1}", sParameter, sParameter.GetType());
        }
        /// <summary>
        /// DateTime類型參數
        /// </summary>
        /// <param name="dtParameter"></param>
        public static void ShowDateTime(DateTime dtParameter)
        {
            Console.WriteLine("This is ShowDateTime, parameter={0} type={1}", dtParameter, dtParameter.GetType());
        }


        /// <summary>
        /// object類型參數
        /// 1 object是一切類型的父類
        /// 2 通過繼承,子類可以擁有父類的一切屬性和行爲,任何父類出現的地方,都可以用子類來代替
        /// </summary>
        /// <param name="dtParameter"></param>
        public static void ShowObject(object oParameter)
        {
            Console.WriteLine("This is ShowObject, parameter={0} type={1}", oParameter, oParameter.GetType());
        }
    }

}

在這個類中,我們主要是爲了輸出顯示某個變量,但這些變量的數據類型不同,所以我們就要定義多個功能類似的方法來適應不用類型的參數。這樣雖然實現了我們想要的功能,但是太過繁瑣,我們可以通過使用泛型將這幾個方法合併成一個就可以實現這些功能。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyGeneric
{
    public class GenericMethod
    {
        /// <summary>
        /// 泛型
        ///    參數類型可變的
        /// 類型在調用的時候確定
        /// 
        /// 延遲思想:推遲一切可以推遲的
        /// 
        /// 怎麼實現的:.net framework 2.0  編譯器升級   
        ///           升級了jit
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void Show<T>(T tParameter)
        {
            Console.WriteLine("This is Show<T>, parameter={0} type={1}", tParameter, tParameter.GetType());

        }
   }

這就是採用泛型來定義的方法。上述定義的是泛型方法。與定義普通方法最大的不同就是在方法名後多了<T> 這裏的T可以代表任何的數據類型,不管是之類型還是引用類型,當在用泛型定義方法時,因爲不確定參數的數據類型,所以就用T來代表某種數據類型的名稱,當代碼在編譯時確定T所具體指代的數據類型。

我們再來學習如何調用泛型方法

 GenericMethod.Show<object>(oValue);
GenericMethod.Show<int>(iValue);
GenericMethod.Show<int>(sValue);//類型參數和參數類型必須一致
GenericMethod.Show(iValue);
GenericMethod.Show<string>(sValue);
GenericMethod.Show<DateTime>(dtValue);

與調用普通方法不同的是,在調用泛型方法時,在方法名和方法參數間要加上<typeparam>用來指定在調用該方法時T具體代表的數據類型。

2 泛型類
首先我們採用普通方法
namespace Wrox.ProCSharp.Generics
{
public class LinkedListNode
{
public LinkedListNode(object value)
{
Value = value;
} public object Value { get; }

public LinkedListNode Next { get; internal set; }
public LinkedListNode Prev { get; internal set; }

}

}`
using System.Collections;

namespace Wrox.ProCSharp.Generics
{
public class LinkedList : IEnumerable
{
public LinkedListNode First { get; private set; }
public LinkedListNode Last { get; private set; }

public LinkedListNode AddLast(object node)
{
  var newNode = new LinkedListNode(node);
  if (First == null)
  {
    First = newNode;
    Last = First;
  }
  else
  {
    Last.Next = newNode;
    Last = newNode;
  }
  return newNode;
}

public IEnumerator GetEnumerator()
{
  LinkedListNode current = First;
  while (current != null)
  {
    yield return current.Value;
    current = current.Next;
  }
}

}

}


using static System.Console;

namespace Wrox.ProCSharp.Generics
{
class Program
{
static void Main()
{
var list1 = new LinkedList();
list1.AddLast(2);
list1.AddLast(4);
// list1.AddLast(“6”);

  foreach (int i in list1)
  {
    WriteLine(i);
  }

}

}
}


接下來我們再來採用泛型類來實現


namespace Wrox.ProCSharp.Generics
{
  public class LinkedListNode<T>
  {
    public LinkedListNode(T value)
    {
      Value = value;
    }

    public T Value { get; }
    public LinkedListNode<T> Next { get; internal set; }
    public LinkedListNode<T> Prev { get; internal set; }
  }
}

using System.Collections;
using System.Collections.Generic;

namespace Wrox.ProCSharp.Generics
{
public class LinkedList : IEnumerable
{
public LinkedListNode First { get; private set; }
public LinkedListNode Last { get; private set; }

public LinkedListNode<T> AddLast(T node)
{
  var newNode = new LinkedListNode<T>(node);
  if (First == null)
  {
    First = newNode;
    Last = First;
  }
  else
  {
    Last.Next = newNode;
    Last = newNode;
  }
  return newNode;
}

public IEnumerator<T> GetEnumerator()
{
  LinkedListNode<T> current = First;

  while (current != null)
  {
    yield return current.Value;
    current = current.Next;
  }
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

}

}


using static System.Console;

namespace Wrox.ProCSharp.Generics
{
class Program
{
static void Main()
{
var list2 = new LinkedList();
list2.AddLast(1);
list2.AddLast(3);
list2.AddLast(5);

  foreach (int i in list2)
  {
    WriteLine(i);
  }

  var list3 = new LinkedList<string>();
  list3.AddLast("2");
  list3.AddLast("four");
  list3.AddLast("foo");

  foreach (string s in list3)
  {
    WriteLine(s);
  }
}

}
}

定義泛型類也就是在定義類時要在類名後加上<T>,然後咋定義類的細節時,用T來代替不確定的數據類型名稱,當然在實例化一個對象時也要額外地加上T具體代表的數據類型。
使用泛型可避免拆包和裝包時的性能損失。

3 泛型約束
泛型約束是在在定義泛型類時,對T所指代的數據類型的約束。通過添加where語句來實現

``具體含義如下表所示

這裏寫圖片描述

接下來介紹下具體的實現代碼
例如聲明一個泛型類,T必須是引用類型,切必須有默認構造函數

class myClass<T> 
       where T : struct, new()
{
}

c#的泛型就介紹到這,這只是泛型的入門,大家學習完以上內容後可再學習一下相關書籍上的有關內容。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章