高级C#技术(二)

news2024/11/15 17:40:27

前言

本章为高级C#技术的第二节也是最后一节。前一节在下面这个链接

高级C#技术icon-default.png?t=N7T8https://blog.csdn.net/qq_71897293/article/details/134930989?spm=1001.2014.3001.5501

匿名类型

匿名类型如其名,匿名的没有指定变量的具体类型。

举个例子:

1 创建一个类

    public class Student
    {
        public int Age { get; set; }
        public int Weight { get; set; }
        public string Name { get; set; }
    }

2 创建一个Student的实例化,并且将这个类的所有成员进行了一个初始化

 Student student = new Student
 {
     Age = 10,
     Weight = 100,
     Name = "",
 };

示例解释:当前代码的写法是上一节提到的对象初始化器。

创建一个匿名类型:

var Variable = new
{
    Age = 10,
    Weight = 100,
    Name = "",
};

示例解释:

        1 使用了var 关键字 ,因为匿名函数没有可以使用的标识符(类型)
        2 new 关键字后没有举明具体类型,等于是告诉编译器我们需要使用匿名类型
        3 在系统的智能提示中,我们鼠标放在变量类型上都会显示相应的变量类型。 而匿名类型则是用a来表示。       

图例:

注意:当前匿名类型不是创建了Student的实例,而是一个自定义的匿名类型两者没有关系。

使用匿名类型:

var s = Variable.Age;//可以通过创建的匿名类型,拿到匿名类型的成员,但这些数据是只读的

注意:可以通过创建的匿名类型,拿到匿名类型的成员,但这些数据是只读的 

扩展(此处引入书上源码)

var animals = new[]
{
    new { Name = "Benjamin", Age = 42, Weight = 185 },
    new { Name = "Benjamin", Age = 42, Weight = 185 },
    new { Name = "Andrea", Age = 46, Weight = 109 }
};
WriteLine(animals[0].ToString());
WriteLine(animals[0].GetHashCode());
WriteLine(animals[1].GetHashCode());
WriteLine(animals[2].GetHashCode());
WriteLine(animals[0].Equals(animals[1]));
WriteLine(animals[0].Equals(animals[2]));
WriteLine(animals[0] == animals[1]);
WriteLine(animals[0] == animals[2]);
ReadKey();

示例解释:

        当前的var animals=new [] 这里是使用了我们前面的类型推理,在当前这个匿名类型对象数组当中,我们创建了多个匿名类型。然后调用了几种不同的方法后输出结果。

        GetHashCode:返回一个对象的哈希码(整数数值)可以用于储存在哈希表等数据结构中。在数组当中的前两个有着相同的属性值,即返回的哈希值是相同的。

        Equals:匿名函数上就是比较一个对象的每个属性与另一个的对应属性值是否相同。如果相同则返回true。

        ==:比较比较对象引用。与方法Equals一致,但在匿名函数中的Equals不是一致。     

输出结果:

{ Name = Benjamin, Age = 42, Weight = 185 }
-1144474565
-1144474565
-977821549
True
False
False
False

提问:创建匿名类型时,如果是是多个相同类型的参数,会创建多个匿名类型吗?像我们前面扩展中创建的方式。


答:不会,会创建同一个匿名类型的多个实例。

动态查找

        动态查找:1 希望使用C#处理另一种语言创建的对象。2 处理未知类型的C#对象,如前一章使用了简单的反射来访问与类型关联的特性。

动态类型

动态类型我不好解释我们直接看它的定义方式,以及使用方式。

定义 (关键字dynamic)  :

public dynamic dongtaitype;

注意:        

        上述代码我们就已经定义了一个动态类型,但它与我们前面的var关键字不同var的关键字它并不是一个类型,而我们这里定义的'dongtaitype'它叫动态类型。一旦有了动态类型我们就可以继续访问其他成员。 

namespace MY
{
    class Program
    {
        public static dynamic dongtaitype;
        static void Main()
        {
            dongtaitype.ToString();
        }
    }
}

示例解释:我们这里直接用当前我们创建的动态类型直接调用了ToString方法。


注意:

        我这里并没有实现ToString方法也并没有给我们的动态类型进行一个初始化。所以它现在的值是"null" 。但编译器并不会报错。编译器还是会在运行的时候去调用这个方法,但当前变量是null所以这无法调用,编译器会抛出异常。


警告:我们在使用动态类型的情况下,我们尽量在只能使用动态类型的情况下再去使用它。如非.net对象,我的理解就是非C#语言创建的对象

接下来我大家看一个动态类型的例子(引在书上示例):

using Microsoft.CSharp.RuntimeBinder;
using static System.Console;
namespace My
{
    class MyClass1
    {
        public int Add(int var1, int var2) => var1 + var2;
    }
    class MyClass2 { }
    class Program
    {
        static int callCount = 0;
        static dynamic GetValue()
        {
            if (callCount++ == 0)
            {
                return new MyClass1();
            }
            return new MyClass2();
        }
        static void Main(string[] args)
        {
            try
            {
                dynamic firstResult = GetValue();
                dynamic secondResult = GetValue();
                WriteLine($"firstResult is: {firstResult.ToString()}");
                WriteLine($"secondResult is: {secondResult.ToString()}");
                WriteLine($"firstResult call: {firstResult.Add(2, 3)}");
                WriteLine($"secondResult call: {secondResult.Add(2, 3)}");
            }
            catch (RuntimeBinderException ex)
            {
                WriteLine(ex.Message);
            }
            ReadKey();
        }
    }
}

示例解释:

        当前我们定义了两个类一个是MyClass1 一个是MyClass2 。其中MyClass1 当中我们定义了一个Add的一个方法。MyClass2 我们没有定义任何成员。在程序主入口Main函数当中我们定义了两个动态类型并且调用了返回动态类型的方法。那么在我们第一次调用GetValue这个方法的时候它会为我们返回一个MyClass1 的实例。在我们第二次调用的时候会返回一个MyClass2 的实例。随后我们使用我们拿到的动态类型去调用我们的ToString方法在这个我们是可以调用的,它实际是一个类型的实例化,当然也可以调用我们父类的ToString方法。那么重要的是我们输出语句的第三个输出语句,我们调用了一个Add的方法我们当前第一个动态类型是没有问题。但是下面那个MyClass2 的实例。这个动态类型它是无法调用因为它根本就没有当前方法。所以这里我们会抛出一个异常会提示“My.MyClass2”未包含“Add”的定义。 然后我们再对抛出的异常进行一个打印异常消息随后这个代码就结束了 

 高级方法参数

高级方法参数:允许使用命名参数和可选参数对方法的一个使用和定义

可选参数

定义方法时某些参数是可选的,而并非像常见方法的参数,要进行重载才能实现相同效果。

示例:

using System;
using Microsoft.CSharp.RuntimeBinder;
using static System.Console;
namespace My
{
    class Program
    {

        static void Main(string[] args)
        {
            WStudent("zhangsan", 15);
            WStudent("李四");
            ReadKey();
        }
        #region 重载实现

        static void WrileStudent(string str)
        {
            WriteLine(str);
        }
        static void WrileStudent(string str, int age)
        {
            WriteLine(str + age);
        }
        #endregion

        #region 可选参数
        static void WStudent(string str, int age = 0)
        {
            WriteLine(str + age);
        }
        #endregion
    }
}

示例解释:

        当前我们给”WrileStudent“方法提供了两个重载的方法。当然我们在下面又定义了一个效果相同的一个方法。其中int age=0 我们在这里其实就是定义了一个可选参数。我们在需要使用它的时候则给它传值,不需要可以直接忽略不传。

1 可选参数的值:默认值必须是:字面值、常量值、默认值类型值。

2 Optional特性:我们也可以使用当前特性定义可选参数

  static void WStudent(string str, [Optional] string ll, int age = 0)
  {
      WriteLine(str + age+ ll);
  }

3 可选参数的顺序 :

  • 可选参数必须位于方法参数列表的末尾
  • 没有默认值的参数不能放在有默认值参数的后面 

命名参数

  //使用
  static void Main(string[] args)
  {
      WStudent("李四", age: 10, ll: "");
      ReadKey();
  }

 //定义
  static void WStudent(string str, [Optional] string ll, int age = 0,int A=0,int B=10)
  {
     WriteLine(str + age + ll);
  }

注意:使用方式时参数名+":"+值。


提示: 

        1 使用命令参数时可以指定需要的任意多个参数,而且参数的顺序是任意的。

        2 命名参数也是可选的 

        3 当方法签名中有多个可选参数和一些必选参数时,可以先指定必选参数,然后再指定需要使用到的可选参数。

Lambda表达式

         Lambda表达式是一种结构,简化C#编程的某些方面。Lambda表达式与其他的C#语言特性结合起来使用及其有用。如和匿名方法结合使用。

提示:匿名方法中 我们不要使用:My.lapsed+=Wrile; 这里是直接将一个方法赋值给事件。这样做会使代码更难理解也不清楚会发生什么  

把lambda表达式用于匿名方法

        在前面我们介绍了匿名方法的使用这里我将演示用lambda表达式替换匿名方法。在使用之前我有必要和你介绍lambda表达式的组成成分,分为三步。

第一部分:在括号当中放参数列表

第二部分:运算符

第三部分:我们的C#语句

举个例子:

using System;
using System.Timers;
namespace My
{
    class Program
    {
        static void Main(string[] args)
        {
            Timer timer=new Timer(100);
            timer.Elapsed += delegate (object sender, ElapsedEventArgs e)
            {
                //事件处理代码
            };
            //lambda 表达式替换匿名函数
            timer.Elapsed += (sender, e) => Console.Write("Hello");
        }
    }
}

示例解释:

        当前我们就做了一个lambda表达式替换匿名函数的一个示例。其中括号当中的就是我们的参数列表其他的部分也是按照我们上面所提到的三个部分所组成我们一个完整的lambda表达式 

Lambda表达式的参数

        Lambda表达式使用类型推理功能来确定所传递的参数类型。我们上述的一个示例并没有指定类型的情况下我们就是使用的它的一个类型推理功能,一个称为隐式类型化的Lambda表达式但如果我们指定了参数列表,当中的参数类型。那么它就被称为一个显示的Lambda表达式 

举个例子:

//显式lambda 表达式
timer.Elapsed += (object sender, ElapsedEventArgs e) => Console.Write("Hello");
//隐式lambda 表达式
timer.Elapsed += (sender, e) => Console.Write("Hello");

注意:

        1 在表达式当中你要么就全部显式类型要么就全部隐式类型。不能一个显式类型一个隐式类型 

        2 定义没有参数的 Lambda 表达式 则使用空括号来表达

举个例子:(sender) => Console.Write("Hello");

        3 定义单个参数的 Lambda 表达式 则不需要用括号  sender => Console.Write("Hello");

Lambda表达式的语句体

        我们其实可以在表达式的语句体中包含多个语句,为此我们就可以用花括号将我们的代码块放在其中。

举个例子:

timer.Elapsed += (object sender, ElapsedEventArgs e)=>
{ 
  //放入代码块
};

        当我们lambda表达式 需要返回除void类型的其他类型,那么我们就要用上关键字 return 进行返回值,和我们在方法中一样。

提示(引入书上原文):如果需要多个语句则定义一个单独的非并匿名方法来代替lambda表达式比较好。

Lambda表达式用作委托和表达式树

        Lambda表达式其实是一个委托,你可以把Lambda表达式赋值给一个委托类型的变量。如我们前面的几个示例一样。但是在system名称空间中已经为我们提供了一些委托类型。所以在很多情况下我们都可以使用这些泛型委托类型而不必定义自己的泛型委托类型。

举例:

泛型类型参数列表个数返回类型
Action表示Lambda表达式     不带参数Void
Action<>表示Lambda表达式最多八个参数Void
Func<>表示Lambda表达式最多八个参数不是Void

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1311429.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL数据库,视图、存储过程与存储函数

数据库对象&#xff1a; 常见的数据库对象&#xff1a; 视图&#xff1a; 视图是一种虚拟表&#xff0c;本身是不具有数据的占用很少的内存空间。 视图建立在已有表的基础上&#xff0c;视图赖以建立的这些表称为基表。 视图的创建和删除只影响视图本身&#xff0c;不影响对…

案例058:基于微信小程序的智能社区服务管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

计算机设计大赛信息可视化设计的获奖经验剖析解读—基于本专栏文章助力4C大赛【全网最全万字攻略-获奖必读】

文章目录 一.中国大学生计算机设计大赛1.1赛道解读1.2 信息可视化设计小类介绍1.2 小类区别解读 二.信息可视化设计赛道获奖经验2.1 四小类作品预览2.1.1 数据可视化小类-优秀参赛作品展览2.1.2 信息图形设计小类-优秀参赛作品展览2.1.3 动态信息影像&#xff08;MG动画&#x…

2024免费mac苹果电脑系统电脑管家CleanMyMac X

macOS已经成为最受欢迎的桌面操作系统之一&#xff0c;它提供了直观、简洁的用户界面&#xff0c;使用户可以轻松使用和管理系统。macOS拥有丰富的应用程序生态系统&#xff1b;还可以与其他苹果产品和服务紧密协作&#xff0c;如iPhone、iPad&#xff0c;用户可以通过iCloud同…

理解JSX:提高前端开发效率的关键(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

spring 笔记五 SpringMVC的数据响应

文章目录 SpringMVC的数据响应SpringMVC的数据响应方式回写数据 SpringMVC的数据响应 SpringMVC的数据响应方式 页面跳转 直接返回字符串通过ModelAndView对象返回 回写数据 直接返回字符串返回对象或集合 返回字符串形式 直接返回字符串&#xff1a;此种方式会将返回的字符…

nodejs+vue+微信小程序+python+PHP血液中心管理平台的设计与实现-计算机毕业设计推荐

实现采血的完整功能&#xff0c;系统用户主要分为两类&#xff0c;一类是管理员&#xff0c;一类是采血工作人员。管理员主要对采血工作人员以及血库进行管理。派发账号给员工作为采血工作人员&#xff0c;对血库的出库入库进行信息化管理。采血工作人员主要完成采血工作。通过…

jmeter,通过Ant插件生成html报告,展示接口详细信息

一、下载Ant 下载地址&#xff1a;Apache Ant - 二进制发行版 二、安装 1、Ant环境变量 解压Ant目录&#xff1b;配置系统环境变量&#xff0c;添加ANT_PATH&#xff0c;值为D:\Software\Ant_plugIn\apache-ant-1.10.14配置系统环境变量Path&#xff0c;添加Ant路径 %ANT_H…

MyBatisPlus基础入门笔记

MyBatisPlus基础入门笔记&#xff0c;源码可见下载链接 大家阅读时可善用目录功能&#xff0c;可以提高大家的阅读效率 下载地址&#xff1a;MyBatisPlus源码笔记 初识MyBatisPlus 入门案例 SpringBoot整合MyBatis&#xff08;复习&#xff09; 创建SpringBoot工程勾选使用的…

设计模式——适配器模式(结构型)

引言 适配器模式是一种结构型设计模式&#xff0c; 它能使接口不兼容的对象能够相互合作。 问题 假如你正在开发一款股票市场监测程序&#xff0c; 它会从不同来源下载 XML 格式的股票数据&#xff0c; 然后向用户呈现出美观的图表。 在开发过程中&#xff0c; 你决定在程序…

使用qt实现四则运算计算机项目

这是我们要包含的头文件 #include <QWidget> #include<QStack> #include<string.h> #include<string> 这是我在ui界面创建的计算机基础框架。 接下来要实现按住每个按钮在白框内显示&#xff1b; 因此我们要定义一个QString 类型的变量 QString e…

nginx服务前端访问查看无响应的问题

问题 nginx 启动之后&#xff0c;前端访问无数据&#xff0c;F12 查看&#xff0c;提示挂起。 以为是配置问题&#xff0c;查看配置文件&#xff0c;未发现配置的有问题。 原因 通过查看配置文件&#xff0c;发现转发的服务地址为127.0.0.1&#xff0c;手动ping 127.0.0.1&a…

AI人工智能与云原生:创新科技的完美结合

人工智能&#xff08;AI&#xff09;是当今科技领域的热门话题&#xff0c;而云原生则是一种新兴的软件开发和部署模式。AI人工智能与云原生的结合&#xff0c;为现代技术创新提供了无限的可能性。本文将探讨AI与云原生的关系&#xff0c;并介绍其如何在实际应用中实现协同效应…

谷歌宣布向云计算客户开放 Gemini Pro,开发者可用其构建应用

12 月 14 日消息&#xff0c;美国时间周三&#xff0c;谷歌宣布了一系列升级的人工智能&#xff08;AI&#xff09;功能&#xff0c;旨在为其云计算客户提供更好的服务。这家科技巨头正试图赶上竞争对手&#xff0c;比如微软和 OpenAI&#xff0c;它们都在积极利用人工智能的热…

docker安装最新版SQL Server并还原备份的数据库

docker安装数据库 拉取微软官方最新版镜像 docker pull mcr.microsoft.com/mssql/server 拉去镜像并创建容器 docker run -e "ACCEPT_EULAY" -e "SA_PASSWORDsa_password_123456" -p 1433:1433 -v /opt/:/opt --name sqlserver -d mcr.microsoft.com/ms…

〖大前端 - 基础入门三大核心之JS篇(54)〗- 原型和原型链

说明&#xff1a;该文属于 大前端全栈架构白宝书专栏&#xff0c;目前阶段免费&#xff0c;如需要项目实战或者是体系化资源&#xff0c;文末名片加V&#xff01;作者&#xff1a;哈哥撩编程&#xff0c;十余年工作经验, 从事过全栈研发、产品经理等工作&#xff0c;目前在公司…

LOF基金跟股票一样吗?

LOF基金&#xff0c;全称为"上市型开放式基金"&#xff0c;是一种可以在上海证券交易所认购、申购、赎回及交易的开放式证券投资基金。投资者可以通过上海证券交易所场内证券经营机构或场外基金销售机构进行认购、申购和赎回基金份额。 LOF基金的特点是既可以像股票…

三层交换机原理与配置

文章目录 三层交换机原理与配置一、三层交换技术概述二、传统的 MLS三、基于CEF 的MLS1、转发信息库&#xff08;FIB&#xff09;2、邻接关系表3、工作原理&#xff1a; 四、三层交换机的配置1、三层交换机配置命令2、三层交换机配置步骤 三层交换机原理与配置 一、三层交换技…

微服务 Nacos服务注册与发现

一、Nacos 功能介绍 在微服务架构下&#xff0c;一个业务服务会被拆分成多个微服务&#xff0c;各个服务之间相互通信完成整体的功能。另外&#xff0c;为了避免单点故障&#xff0c;微服务都会采取集群方式的高可用部署&#xff0c;集群规模越大&#xff0c;性能也会越高&…

linux磁盘空间清理

查看磁盘使用情况 查看磁盘分区上可以使用的磁盘空间 $ df -h若要查看文件类型和block&#xff0c;使用下面的命令 $ df -T查看每个文件和目录的磁盘使用空间&#xff0c;也就是文件的大小。 $ sudo du -sh /* $ sudo du -h --max-depth1 /清理旧的 Snap 包版本以释放磁盘空…