C#学习笔记10 泛型,partial,Lambda

泛型

image-20210331215750894

  • 泛型无处不在,和谁都有一腿,泛化即模糊抽象化,比如听音乐和听周杰伦的歌,听青花瓷,这就是泛化->特化
  • 泛型的重要,除了它无处不再外,常用的数据结构都是泛型的。
  • 缺点,泛型T实际上在类中只能当作object使用

image-20210331220515518

为什么需要泛型

类型膨胀

一个商品对应一个盒子,盒子类型膨胀了

image-20210331221310901

成员膨胀

一个盒子装了苹果后,就不装了,其实这盒子还能装书的,这样就浪费了

image-20210331221543566

其他方法

如果使用一个接口或者粗俗点用object声明变量,那么使用这对象的时候,需要判断其类型,然后进行类型转换

泛型登场拯救世界

public Box<类型参数>{},类型参数是一个标识符,代表一个泛化类型,就像上面的音乐,而传入的值是音乐中的一个特化,《青花瓷》。

注意!注意!注意! C# 泛型类必须特化只会才能够使用,这点与JAVA不同,JAVA是特化不是必须的。不特化相当于传入了一个object。特化了就清楚其方法属性了,是强类型的。

    class Box<T>
    {
        public T SomeThing { get; set; }
    }

image-20210331223336248

泛型接口

使用方法一

image-20210331223910254

使用方法二

和一的主要区别就是让Student的ID类型定死了ulong

image-20210331224028174

其他

根据C#必须泛型类特化这特性,那么很多接口都要有泛型版和不泛型版哈哈哈,例如下面的哈哈

image-20210331224706727

泛型方法

方法的成员膨胀更加麻烦,因为这意味着一个方法的逻辑错了,就需要改全部膨胀出来的方法

image-20210401151945707

这里的会自动特化

泛型委托

由于T类型是不能直接使用+号的,所以这里随便乱来了。可以发现,Add方法中T自动赋予了int类型,如果T的操作正常点的化,string也可以作为T的。

    class Program
    {
        static void Main(string[] args)
        {
            Func<int, int, string> func = Add;
            Console.WriteLine(func(1,2));
        }
        static string Add<T>(T a, T b)
        {
            Console.WriteLine(a);
            Console.WriteLine(b);
            return a.ToString() + b.ToString();
        }
    }

由于T类型不能直接使用运算符+,使用这里只能成员膨胀一下,或者写复杂点的代码

image-20210401160814207

或者采用Lambda表达式,泛型搭配Lambda神器啊!!!!!!

        static void Main(string[] args)
        {
            Func<int, int, int> func =(a,b)=>
            {
                return a + b;
            };
            Console.WriteLine(func(1,2));
        }

partial分部类型

可以解决数据库中生成代码重置问题。

通过分部类型可以定义要拆分到多个文件中的类、结构、接口或记录。

在 File1.cs 中:

namespace PC
{
    partial class A
    {
        int num = 0;
        void MethodA() { }
        partial void MethodC();
    }
}

在 File2.cs 中,声明:

namespace PC
{
    partial class A
    {
        void MethodB() { }
        partial void MethodC() { }
    }
}

Lambda 表达式

不同情况三种写法

  1. 无参数直接()=>{}
  2. 单个参数x=>{}
  3. 多个(a,b)=>{}

三种表达

action委托,func委托以及**表达式树**类型

任何 Lambda 表达式都可以转换为委托类型。 Lambda 表达式可以转换的委托类型由其参数和返回值的类型定义。 如果 lambda 表达式不返回值,则可以将其转换为 Action 委托类型之一;否则,可将其转换为 Func 委托类型之一。 例如,有 2 个参数且不返回值的 Lambda 表达式可转换为 Action 委托。 有 1 个参数且不返回值的 Lambda 表达式可转换为 Func 委托。 以下示例中,lambda 表达式 x => x * x(指定名为 x 的参数并返回 x 平方值)将分配给委托类型的变量:

Func<int, int> square = x => x * x;
Console.WriteLine(square(5));
// Output:
// 25

表达式 lambda 还可以转换为**表达式树**类型,如下面的示例所示:

System.Linq.Expressions.Expression<Func<int, int>> e = x => x * x;
Console.WriteLine(e);
// Output:
// x => (x * x)

可在需要委托类型或表达式树的实例的任何代码中使用 lambda 表达式,例如,作为 Task.Run(Action) 方法的参数传递应在后台执行的代码。

关于LINQ

用 C# 编写 LINQ 时,还可以使用 lambda 表达式,如下例所示:

int[] numbers = { 2, 3, 4, 5 };
var squaredNumbers = numbers.Select(x => x * x);
Console.WriteLine(string.Join(" ", squaredNumbers));
// Output:
// 4 9 16 25

如果使用基于方法的语法在 System.Linq.Enumerable 类中(例如,在 LINQ to Objects 和 LINQ to XML 中)调用 Enumerable.Select 方法,则参数为委托类型 System.Func

如果在 System.Linq.Queryable 类中(例如,在 LINQ to SQL 中)调用 Queryable.Select 方法,则参数类型为表达式树类型 Expression>。 在这两种情况下,都可以使用相同的 lambda 表达式来指定参数值。 尽管通过 Lambda 创建的对象实际具有不同的类型,但其使得 2 个 Select 调用看起来类似。

异步 lambda

通过使用 asyncawait 关键字,你可以轻松创建包含异步处理的 lambda 表达式和语句。 例如,下面的 Windows 窗体示例包含一个调用和等待异步方法 ExampleMethodAsync的事件处理程序。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click += button1_Click;
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        await ExampleMethodAsync();
        textBox1.Text += "\r\nControl returned to Click event handler.\n";
    }

    private async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

你可以使用异步 lambda 添加同一事件处理程序。 若要添加此处理程序,请在 lambda 参数列表前添加 async 修饰符,如下面的示例所示:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click += async (sender, e) =>
        {
            await ExampleMethodAsync();
            textBox1.Text += "\r\nControl returned to Click event handler.\n";
        };
    }

    private async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

特殊情况

表达式 lambda 的主体可以包含方法调用。 不过,若要创建在 .NET 公共语言运行时 (CLR) 的上下文之外(如在 SQL Server 中)计算的表达式树,则不得在 lambda 表达式中使用方法调用。 在 .NET 公共语言运行时 (CLR) 上下文之外,方法将没有任何意义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值