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 获取页面元素的父元素,子元素。

以上便是对泛型方法的总结,记录下来以便以后查阅.

posted @ 2020-11-14 18:32  BigBosscyb  阅读(1573)  评论(2编辑  收藏  举报