1. 程式人生 > 實用技巧 >C#:泛型方法

C#:泛型方法

在上一篇講了泛型的基本概念後,本篇將走進泛型的應用。

泛型方法:

第一步:宣告泛型方法

  • 方法名後面使用<>,然後在<>中放置型別引數列表
  • 在方法的引數列表中,使用型別引數
  • 在方法引數列表後,使用約束子句(這一步不是必選的)
/// <summary>
/// 比較兩個數的大小
/// </summary>
/// <typeparam name="TTT">實現了ICompare介面的任何型別</typeparam>
/// <param name="tT1"></param>
/// <param name="tT2"></param>
/// <returns>若tT1<tT2則返回true,否則返回false</returns>
static bool IsLessThan<TTT>(TTT tT1, TTT tT2) where TTT : IComparable
{
    return tT1.CompareTo(tT2) < 0 ? true : false;
}

第二步:呼叫泛型方法---要呼叫泛型方法,就要在呼叫時提供型別實參

static void Main(string[] args)
{
    bool isLessThan1 = IsLessThan<int>(12, 11);
    Console.WriteLine(isLessThan1);
    bool isLessThan2 = IsLessThan<int>(1, 11);
    Console.WriteLine(isLessThan2);
    Console.ReadLine();
}
/*
執行結果:
False
True
*/

泛型方法具有型別推斷能力


當我們呼叫方法時,編譯器由傳入的實參的型別能夠推斷出型別引數的型別,所以呼叫泛型方法時可以不寫"<型別引數>"

通過實戰練習使用泛型方法

首先是WPF的XAML佈局檔案

<Window x:Class="VisualTreeSearch.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:VisualTreeSearch"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid x:Name="outergrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Slider Maximum="100" Minimum="0" Value="20" ValueChanged="Slider_ValueChanged"/>
        <ContentControl x:Name="rgbControl" Grid.Row="1">
            <ContentControl.Template>
                <ControlTemplate>
                    <StackPanel>
                        <RadioButton x:Name="red" Foreground="Red" Content="紅燈" GroupName="rgb"/>
                        <RadioButton x:Name="green" Foreground="Green" Content="綠燈" GroupName="rgb"/>
                        <RadioButton x:Name="yellow" Foreground="Yellow" Content="黃燈" GroupName="rgb"/>
                    </StackPanel>
                </ControlTemplate>
            </ContentControl.Template>
        </ContentControl>
    </Grid>
</Window>

介面截圖

  • 需求:通過拖動滑塊,滑塊的值從左到右慢慢在增大;當滑塊的值增大過程中黃、綠、紅單選按鈕依次被選中。**
  • 問題是:由於RadioButton是裝在控制元件模板中的,所以無法在XAML檔案對應的.cs檔案中直接通過空間Name操作RadioButton。**
  • 分析:根據控制元件名獲取子控制元件是一個通用的問題,它不因要獲取的那個控制元件的型別而使問題的本質發生改變,即:寫出一個通用方法,它能夠接受一個要查詢的子控制元件的name和子控制元件所在的父控制元件的例項;通過執行一系操作最終給我們返回一個目標子控制元件例項

定義一個可從目標控制元件所在的父控制元件中查詢到名字為該控制元件的泛型方法

  • 定義泛型方法(可以將本方法定義在一個獨立的cs檔案中,讓此方法能夠成為你專案中的工具方法)
/// 查詢子元素
/// </summary>
/// <typeparam name="T">子元素型別</typeparam>
/// <param name="obj">父元素</param>
/// <param name="name">子元素name</param>
/// <returns>若查詢到子元素則返回子元素型別例項;否則返回null值</returns>
public static T GetChildObject<T>(DependencyObject obj, string name) where T : FrameworkElement
{
    DependencyObject child = null;
    T grandChild = null;
    for (int i = 0; i <= VisualTreeHelper.GetChildrenCount(obj) - 1; i++)
    {
        child = VisualTreeHelper.GetChild(obj, i);
        if (child is T && (((T)child).Name == name | string.IsNullOrEmpty(name)))
        {
            return (T)child;
        }
        else
        {
            grandChild = GetChildObject<T>(child, name);
            if (grandChild != null)
                return grandChild;
        }
    }
    return null;
}
  • 根據滑塊的值的變化,操作RadioButton的選中狀態
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    if (rgbControl != null)
    {
        RadioButton radioButton;
        if (e.NewValue < 40)
        {
            radioButton = MyVisualTreeHelper.GetChildObject<RadioButton>(rgbControl, "yellow");
        }
        else if (e.NewValue < 80)
        {
            radioButton = MyVisualTreeHelper.GetChildObject<RadioButton>(rgbControl, "green");
        }
        else
        {
            radioButton = MyVisualTreeHelper.GetChildObject<RadioButton>(rgbControl, "red");
        }
        if (radioButton != null)
        {
            radioButton.IsChecked = true;
        }
    }
    e.Handled = true;
}
  • 執行效果

關於類似的需要查詢所以目標型別的子控制元件、以及查詢目標型別的父控制元件的擴充套件方法請看這篇部落格:Wpf 獲取頁面元素的父元素,子元素。

以上便是對泛型方法的總結,記錄下來以便以後查閱.