软件开发面试题(C#语言,.NET框架)

1. 解释什么是委托(Delegate),并举例说明它在C#中的用法。

        委托是一种引用类型,它可以用于封装一个或多个方法。委托对象可以像方法一样调用,甚至可以用于创建事件处理程序。委托是C#中实现事件和回调函数的重要机制。

委托的基本语法:

  1. 定义委托
    public delegate void MyDelegate(string message);
  2. 创建委托实例
    MyDelegate del = new MyDelegate(MethodToCall);
  3. 调用委托
    del("Hello, World!");

 示例:

using System;public class Program
{// Step 1: Define a delegatepublic delegate void MyDelegate(string message);// Step 2: Create a method that matches the delegate signaturepublic static void MethodToCall(string message){Console.WriteLine(message);}public static void Main(){// Step 3: Create an instance of the delegateMyDelegate del = new MyDelegate(MethodToCall);// Step 4: Call the delegatedel("Hello, World!");}
}

在这个示例中,定义了一个委托MyDelegate,它接受一个字符串参数。还定义了一个方法MethodToCall,它与委托的签名匹配。然后,创建了一个MyDelegate实例,并调用它。

委托的应用场景

委托在C#中常用于事件处理、回调函数和实现可插拔的代码模式等场景中。

  1. 事件处理 委托用于定义事件处理程序。C#中的事件机制就是基于委托的。

  2. 回调 委托可以用来实现回调函数。比如,你可以将一个方法传递给另一个方法,以便在特定条件下调用。

  3. 多播委托 一个委托实例可以封装多个方法。这些方法会按顺序执行,这在实现事件广播时非常有用。

  4. 委托的定义和使用

  5. 定义委托:委托通过delegate关键字定义。委托类型声明中指定了方法的签名(返回类型和参数类型)。

    // 定义一个委托类型
    public delegate void MyDelegate(int x, int y);// 另一种方式,使用系统定义的委托类型
    Action<int, int> myAction = (x, y) => Console.WriteLine(x + y);
    

  6. 实例化委托:创建委托实例并指定要调用的方法。

    public class Calculator
    {// 委托实例作为类的字段public MyDelegate AddNumbers;public void PerformAddition(int x, int y){// 调用委托实例,触发绑定的方法AddNumbers?.Invoke(x, y);}
    }
    
  7. 使用委托:将方法绑定到委托实例,然后通过委托实例调用方法。

    class Program
    {static void Main(){Calculator calc = new Calculator();// 绑定方法到委托实例calc.AddNumbers = (a, b) => Console.WriteLine($"Sum: {a + b}");// 调用委托实例触发绑定的方法calc.PerformAddition(5, 3); // 输出:Sum: 8}
    }
    
  8. 在上面的示例中:

    MyDelegate委托类型定义了可以接受两个int参数并且不返回任何内容的方法。Calculator类包含一个AddNumbers委托实例作为其字段,并且有一个方法PerformAddition来调用委托实例。在Main方法中,我们创建了一个Calculator对象,并将一个lambda表达式绑定到AddNumbers委托实例上。最后,调用PerformAddition方法来触发绑定的方法。

2.解释一下C#中的异步编程以及async和await关键字的用法。

异步编程的概念

异步编程是一种编程范式,允许程序在执行耗时操作(如I/O操作、网络请求等)时,不会阻塞主线程或用户界面线程。这样可以提高应用程序的响应性和性能。

asyncawait 关键字

C#引入了asyncawait关键字来简化异步编程,使代码更加简洁和易于理解。

  1. async 关键字

    async关键字用于标记一个方法为异步方法。一个异步方法可以包含一个或多个await表达式。

  2. 用于修饰方法,表示该方法包含异步操作。
  3. async方法可以返回TaskTask<T>void(仅用于事件处理程序)。
  4. await 关键字

    await关键字用于暂停异步方法的执行,直到被等待的任务完成。它会释放当前线程,使其可以执行其他任务。

  5. 用于等待一个异步操作的完成。
  6. await关键字只能在async方法中使用。
  7. 当使用await等待一个任务时,控制权会返回给调用者,允许其他操作继续进行。
    using System;
    using System.Net.Http;
    using System.Threading.Tasks;class Program
    {static async Task Main(string[] args){// 调用异步方法string content = await FetchDataFromUrlAsync("https://jsonplaceholder.typicode.com/todos/1");Console.WriteLine(content);}// 定义一个异步方法static async Task<string> FetchDataFromUrlAsync(string url){using (HttpClient client = new HttpClient()){// 发送异步请求并等待响应HttpResponseMessage response = await client.GetAsync(url);response.EnsureSuccessStatusCode();// 读取响应内容string responseBody = await response.Content.ReadAsStringAsync();return responseBody;}}
    }/*
    Main方法被标记为async,并返回一个Task。
    FetchDataFromUrlAsync方法被标记为async,并返回一个Task<string>。
    在FetchDataFromUrlAsync方法中,使用await等待HttpClient.GetAsync和response.Content.ReadAsStringAsync的完成。
    await关键字允许程序在等待任务完成时,继续处理其他操作,从而提高应用程序的效率和响应性。
    */

  8. using System;
    using System.Net.Http;
    using System.Threading.Tasks;public class Program
    {public static async Task Main(string[] args){Console.WriteLine("Starting download...");string result = await DownloadContentAsync("https://www.example.com");Console.WriteLine("Download completed.");Console.WriteLine(result);}public static async Task<string> DownloadContentAsync(string url){using (HttpClient client = new HttpClient()){string content = await client.GetStringAsync(url);return content;}}
    }
    

解释

  1. Main 方法

    我们在Main方法中调用了一个异步方法DownloadContentAsync并使用await关键字等待其完成。

  2. DownloadContentAsync 方法

    这个方法被标记为async,表示它是一个异步方法。我们使用HttpClient类发送HTTP请求,并使用await关键字等待GetStringAsync方法完成。GetStringAsync方法是一个异步方法,它会返回一个Task<string>

  3. await 关键字

    await关键字会暂停DownloadContentAsync方法的执行,直到GetStringAsync任务完成。完成后,await会返回任务的结果并继续执行方法的其余部分。

异步编程的优势

  1. 提高响应性 异步方法不会阻塞主线程,使得应用程序在处理长时间运行的任务时仍然保持响应。

  2. 简化代码 使用asyncawait关键字可以避免回调地狱,使异步代码更加直观和易于维护。

3.解释一下什么是LINQ,并举例说明如何在C#中使用LINQ查询数据。

什么是LINQ?

LINQ是C#语言中的一种查询技术,它允许开发人员使用类似SQL的语法来查询各种数据源,例如集合、数组、数据库等。LINQ使得数据的查询和操作变得更加直观和简单,并且能够在编译时进行类型检查。

在C#中使用LINQ查询数据的基本步骤

  1. 引入命名空间

    首先,确保在文件开头引入System.Linq命名空间,因为LINQ扩展方法都在这个命名空间中定义。

    using System.Ling
  2. LINQ查询语法

    LINQ查询可以使用两种语法:查询表达式和方法语法。下面我们以方法语法为例进行说明。

    using System;
    using System.Linq;public class Program
    {public static void Main(){// 示例数据源 - 整数数组int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };// LINQ查询语句var query = numbers.Where(n => n % 2 == 0).Select(n => n * n);// 执行查询并输出结果foreach (var result in query){Console.WriteLine(result);}}
    }
    

解释

  • Where 方法

    Where方法用于过滤数据源,筛选出符合特定条件的元素。在示例中,我们使用Where(n => n % 2 == 0)选择所有偶数。

  • Select 方法

    Select方法用于对数据源中的每个元素应用一个转换函数,并返回结果序列。在示例中,我们使用Select(n => n * n)计算每个偶数的平方。

  • 执行查询

    query是一个延迟执行的查询,只有在foreach循环中迭代时才会真正执行查询并输出结果。

LINQ的优势

  1. 统一的查询语法 LINQ提供了一种统一的语法来查询不同类型的数据源,无论是集合、数组、数据库还是XML。

  2. 类型安全和编译时检查 LINQ查询是类型安全的,并且能够在编译时检查语法错误,这减少了运行时错误的可能性。

  3. 简化代码 LINQ使得复杂的数据操作和查询变得简单和可读,减少了样板代码和嵌套结构。

4.解释一下在C#中什么是垃圾回收(Garbage Collection),它是如何工作的?

什么是垃圾回收(Garbage Collection)?

垃圾回收(GC)是一种自动内存管理机制,用于回收程序中不再使用的内存。它可以防止内存泄漏,确保程序的内存使用效率。C#中垃圾回收由CLR(Common Language Runtime)负责管理。

垃圾回收的工作原理

垃圾回收的主要任务是识别和释放那些不再被引用的对象所占用的内存。以下是垃圾回收的工作流程:

  1. 根集合(Root Set) 垃圾回收器首先找到所有活动的对象引用,这些引用通常存储在栈、全局对象、静态对象等地方。这些引用被称为根集合。

  2. 标记阶段(Marking Phase) 垃圾回收器从根集合开始,递归地标记所有可达的对象。被标记的对象被认为是活动的,不能被回收。

  3. 清除阶段(Sweeping Phase) 垃圾回收器遍历内存中的所有对象,清除那些未被标记的对象,释放它们占用的内存。

  4. 压缩阶段(Compacting Phase, 可选) 在某些情况下,垃圾回收器会对内存进行压缩,将存活的对象移动到内存的一端,以减少内存碎片并优化内存使用效率。

垃圾回收的代(Generation)

为了提高性能,C#的垃圾回收器使用了分代回收策略。内存中的对象被分为三代:

  1. 第0代(Generation 0) 包含新创建的对象。因为大多数对象的生命周期很短,垃圾回收器会频繁地对第0代进行回收。

  2. 第1代(Generation 1) 包含那些已经存活过一次第0代回收的对象。第1代回收相对较少。

  3. 第2代(Generation 2) 包含长生命周期的对象。第2代回收最不频繁,但会进行全面回收。

示例

using System;public class Program
{public static void Main(){// 创建一些对象for (int i = 0; i < 1000; i++){var obj = new object();}// 显示垃圾回收前的内存使用情况Console.WriteLine("GC前的内存使用: " + GC.GetTotalMemory(false));Console.ReadLine();// 强制进行垃圾回收GC.Collect();// 显示垃圾回收后的内存使用情况Console.WriteLine("GC后的内存使用: " + GC.GetTotalMemory(true));Console.ReadLine();}
}

 

using System;class Program
{static void Main(){// 创建对象MyClass obj = new MyClass();// 使用对象obj.DoSomething();// 将对象设置为null,表示不再需要它obj = null;// 手动调用GC(通常不需要)GC.Collect();Console.WriteLine("垃圾回收完成");}
}class MyClass
{public void DoSomething(){Console.WriteLine("Doing something");}
}

在这个示例中,我们创建了一些对象,然后使用GC.Collect()方法手动触发垃圾回收,并显示垃圾回收前后的内存使用情况。

垃圾回收的优势

  1. 自动内存管理 程序员不需要手动管理内存,减少了内存泄漏和悬挂指针的风险。

  2. 提高程序的稳定性和安全性 自动内存管理减少了内存管理错误,提高了程序的稳定性和安全性。

5.解释一下C#中的接口(Interface)是什么,以及如何在代码中使用接口。

在C#中,接口(Interface)是一种定义了一组无实现方法的类型。接口只包含方法、属性、事件或索引器的声明,而不包含任何实现。接口用于定义类或结构必须遵循的一组规则。它可以被实现(implement)在一个或多个类或结构中,以确保这些类或结构遵循接口中定义的规则。

示例:

// 定义一个接口
public interface IAnimal
{void MakeSound();void Eat();
}// 实现接口的类
public class Dog : IAnimal
{public void MakeSound(){Console.WriteLine("Bark");Console.ReadLine();}public void Eat(){Console.WriteLine("Dog is eating.");Console.ReadLine();}
}public class Cat : IAnimal
{public void MakeSound(){Console.WriteLine("Meow");Console.ReadLine();}public void Eat(){Console.WriteLine("Cat is eating.");Console.ReadLine();}
}

 在这个例子中,IAnimal接口定义了两个方法:MakeSoundEatDogCat类实现了这个接口,并提供了各自的具体实现。

6.在C#中,抽象类和接口有什么区别?

  1. 实现方式

    • 接口:只能包含方法、属性、事件和索引器的声明,不能包含任何实现。
    • 抽象类:可以包含方法、属性的声明和实现。抽象方法在子类中必须实现,而具体方法可以直接使用或在子类中重写。
  2. 多重继承

    • 接口:一个类可以实现多个接口,这提供了一种方式来实现多重继承。
    • 抽象类:一个类只能继承一个抽象类(或任何其他类),不能多重继承。
  3. 构造函数

    • 接口:不能包含构造函数。
    • 抽象类:可以包含构造函数,供子类调用。
  4. 字段

    • 接口:不能包含字段。
    • 抽象类:可以包含字段。
  5. 访问修饰符

    • 接口:成员默认是public,不能包含其他访问修饰符。
    • 抽象类:可以包含不同访问修饰符(publicprotectedprivate)。

下面是一个例子来说明抽象类和接口的区别:

// 定义一个接口
public interface IAnimal
{void MakeSound();
}// 定义一个抽象类
public abstract class Animal
{public abstract void MakeSound();public void Eat(){Console.WriteLine("Animal is eating.");}
}// 实现接口的类
public class Dog : IAnimal
{public void MakeSound(){Console.WriteLine("Bark");}
}// 继承抽象类的类
public class Cat : Animal
{public override void MakeSound(){Console.WriteLine("Meow");}
}

在这个例子中,IAnimal是一个接口,Animal是一个抽象类。Dog类实现了接口,Cat类继承了抽象类并实现了抽象方法。

7.在C#中,什么是泛型(Generics),以及为什么使用泛型?

在C#中,泛型(Generics)是一种允许你编写可以重用的类型或方法的技术。泛型允许在定义类、结构、接口和方法时使用类型参数,这些类型参数可以在使用时指定具体的类型。使用泛型可以提高代码的灵活性、类型安全性和性能。

泛型的作用和使用方法

  1. 作用

    • 允许编写通用的代码,可以适用于多种数据类型,而不需要重复编写相似的代码。
    • 提高了代码的类型安全性,编译器可以在编译时捕获到类型不匹配的错误。
    • 避免了装箱和拆箱操作,提高了性能。
  2. 使用方法

    • 泛型类:使用<T>语法定义泛型类,其中T是类型参数的占位符。
    • 泛型方法:使用<T>语法定义泛型方法,在方法名之后指定类型参数。
    • 泛型接口:定义泛型接口时,可以在接口名后面使用<T>语法指定类型参数。
using System;// 定义一个泛型类
public class GenericList<T>
{private T[] data;private int index;public GenericList(int size){data = new T[size];index = 0;}public void Add(T item){if (index < data.Length){data[index] = item;index++;}else{Console.WriteLine("List is full.");}}public void Print(){foreach (T item in data){Console.WriteLine(item);}}
}class Program
{static void Main(){// 实例化一个泛型类GenericList<int> intList = new GenericList<int>(5);intList.Add(1);intList.Add(2);intList.Add(3);intList.Print();GenericList<string> stringList = new GenericList<string>(3);stringList.Add("Hello");stringList.Add("World");stringList.Print();}
}

 

在这个例子中,GenericList<T>是一个泛型类,可以用来存储任何类型的数据。在Main方法中,我们实例化了两个泛型类的对象,一个存储整数,一个存储字符串,并演示了如何向泛型类中添加元素并打印它们。

泛型在C#中是一个非常强大和常用的特性,可以大大简化和提高代码的复用性和可维护性。

8.在C#中,什么是异常处理(Exception Handling),如何使用try-catch-finally块来处理异常?

在C#中,异常处理是一种机制,用于捕获和处理程序运行时发生的异常情况,例如除以零、空引用等。异常处理允许程序员在代码中定义如何处理这些异常,从而使程序能够在遇到问题时进行优雅的处理,而不是直接崩溃或产生不可预期的结果。

异常处理的基本方法

异常处理通常使用try-catch-finally块来实现:

  1. try:在try块中编写可能会抛出异常的代码。

  2. catch:在catch块中指定希望捕获的异常类型,并定义异常处理逻辑。

  3. finally:在finally块中编写无论是否发生异常都需要执行的代码,例如资源释放。

以下是一个简单的示例,展示如何使用try-catch-finally块处理异常:

using System;class Program
{static void Main(){try{// 可能会抛出异常的代码int a = 10;int b = 0;int result = a / b; // 除以零会抛出 DivideByZeroExceptionConsole.WriteLine($"Result: {result}"); // 不会执行到这里}catch (DivideByZeroException ex){// 捕获特定类型的异常,并处理Console.WriteLine("Error: Divide by zero");}catch (Exception ex){// 捕获所有其他类型的异常Console.WriteLine($"An error occurred: {ex.Message}");}finally{// 无论是否发生异常,最终都会执行的代码Console.WriteLine("Finally block executed.");}}
}

 

在这个例子中:

  • try块包含了除以零的代码,可能会抛出DivideByZeroException异常。
  • catch块用于捕获DivideByZeroException异常,并输出错误信息。
  • finally块包含了无论是否发生异常都会执行的代码。

catch块可以指定多个,每个catch块可以捕获不同类型的异常,或者可以使用一个通用的catch (Exception ex)捕获所有未处理的异常。finally块是可选的,用于确保资源的释放或其他清理操作。

异常处理使得程序在面对问题时能够做出合适的响应,从而提高了程序的稳定性和可靠性。

9.在C#中,什么是委托链(Delegate Chain),它的作用是什么?

在C#中,委托链(Delegate Chain)是多个委托的组合,这些委托可以依次被调用。委托链允许你在一个委托实例中包含多个方法,当调用这个委托实例时,链中的所有方法都会按顺序执行。

委托链的作用

  • 多播委托:委托链可以看作是多播委托(Multicast Delegate),它允许一个委托实例引用多个方法。
  • 事件处理:在事件处理机制中,委托链用于将多个事件处理程序连接在一起,当事件被触发时,所有处理程序都会被调用。

创建和使用委托链

  1. 定义委托:定义一个委托类型。
  2. 实例化和组合委托:创建委托实例,并使用++=操作符将多个方法添加到委托链中。
  3. 调用委托链:调用委托实例,依次执行链中的所有方法。

以下是一个简单的示例,展示如何创建和使用委托链:

using System;public delegate void MyDelegate(string message);class Program
{static void Main(){// 创建委托实例并将方法添加到委托链中MyDelegate del1 = Method1;MyDelegate del2 = Method2;MyDelegate delChain = del1 + del2;// 也可以使用 += 操作符// MyDelegate delChain = del1;// delChain += del2;// 调用委托链delChain("Hello, world!");}static void Method1(string message){Console.WriteLine("Method1 received: " + message);}static void Method2(string message){Console.WriteLine("Method2 received: " + message);}
}

 

在这个例子中:

  • 定义了一个MyDelegate委托类型,它接受一个字符串参数并返回void
  • Method1Method2是两个与MyDelegate匹配的方法。
  • 使用+操作符将del1del2组合成一个委托链delChain
  • 调用delChain时,Method1Method2会依次被调用,输出传入的消息。

运行结果:

Method1 received: Hello, world!
Method2 received: Hello, world!

委托链在事件处理和回调机制中非常有用,可以将多个处理程序连接在一起,从而实现复杂的处理逻辑。

10.在C#中,什么是事件(Event),以及如何使用事件?

在C#中,事件(Event)是一种特殊的委托,用于实现发布-订阅模式。事件允许对象向外部通知某些动作或状态的变化,而不需要让外部对象知道内部的具体实现细节。事件在GUI编程和异步编程中非常常用。

事件的基本概念和使用方法

  1. 定义事件:事件基于委托类型定义。使用event关键字来声明事件。

  2. 触发事件:在类的内部方法中,通过调用事件委托来触发事件。

  3. 订阅事件:外部对象可以通过+=操作符订阅事件,指定事件触发时要调用的方法。

事件的示例

以下是一个简单的示例,展示如何定义、订阅和触发事件:

using System;// 定义一个委托类型,用于事件处理
public delegate void MyEventHandler(string message);// 发布者类
public class Publisher
{// 使用event关键字定义事件public event MyEventHandler MyEvent;// 触发事件的方法public void RaiseEvent(string message){// 触发事件,检查是否有订阅者MyEvent?.Invoke(message);}
}// 订阅者类
public class Subscriber
{// 事件处理方法public void OnEventRaised(string message){Console.WriteLine("Event received: " + message);}
}class Program
{static void Main(){Publisher publisher = new Publisher();Subscriber subscriber = new Subscriber();// 订阅事件publisher.MyEvent += subscriber.OnEventRaised;// 触发事件publisher.RaiseEvent("Hello, world!");}
}

 

在这个例子中:

  1. 定义事件

    • MyEventHandler是一个委托类型,定义了事件处理方法的签名。
    • Publisher类中,使用event关键字声明了一个事件MyEvent
  2. 触发事件

    • Publisher类中,RaiseEvent方法触发事件,使用?.Invoke来检查是否有订阅者。
  3. 订阅事件

    • Program类中,创建了PublisherSubscriber对象。
    • 使用+=操作符将Subscriber类的OnEventRaised方法订阅到Publisher类的MyEvent事件。

运行结果:

Event received: Hello, world!

事件机制使得发布者和订阅者之间的耦合度降低,提供了一种松散耦合的方式来处理异步通知和回调。

11.在C#中,什么是属性(Property),以及如何使用自动属性?

在C#中,属性(Property)是类、结构和接口中的成员,它提供了对字段的访问控制。属性看起来像是字段,但实际上是方法的特殊组合,用于读取和写入字段的值。属性可以包含逻辑,用于在设置或获取值时执行特定操作。

属性的基本概念和使用方法

  1. 定义属性:属性由getset访问器组成,可以在访问器中定义读取或写入字段时的逻辑。

  2. 自动属性:自动属性是一种简化的语法,它不需要显式定义字段,编译器会自动创建一个私有的匿名字段来存储属性的值。

属性的示例

以下是一个简单的示例,展示如何定义和使用属性:

using System;public class Person
{private string name;// 定义一个属性public string Name{get { return name; }set { name = value; }}// 使用自动属性public int Age { get; set; }public void DisplayInfo(){Console.WriteLine($"Name: {Name}, Age: {Age}");}
}class Program
{static void Main(){Person person = new Person();// 使用属性person.Name = "John";person.Age = 30;person.DisplayInfo(); // 输出:Name: John, Age: 30}
}

 

在这个例子中:

  1. 定义属性

    • Name属性有一个私有字段nameget访问器用于返回name的值,set访问器用于设置name的值。
  2. 自动属性

    • Age属性使用了自动属性语法,编译器会自动生成一个私有的匿名字段来存储Age的值。这样可以简化代码,使其更简洁。

属性提供了对类成员的封装,使得可以在设置或获取值时添加额外的逻辑,从而增强了代码的灵活性和安全性。

属性的常见用法

  1. 只读属性:只包含get访问器的属性,不能修改值。
  2. 写入属性:只包含set访问器的属性,只能设置值,不能读取。
  3. 计算属性:在getset访问器中包含逻辑,用于计算或验证值。
示例:只读属性
public class Circle
{private double radius;public Circle(double radius){this.radius = radius;}// 只读属性public double Circumference{get { return 2 * Math.PI * radius; }}
}

在这个示例中,Circumference属性是一个只读属性,它在get访问器中计算圆的周长。

12.在C#中,什么是匿名方法和Lambda表达式?

在C#中,匿名方法和Lambda表达式是两种用于定义无名称方法的技术。它们主要用于简化代码,特别是在使用委托和事件时。

匿名方法

匿名方法是没有名称的方法,可以在代码中直接内联定义。使用delegate关键字来定义匿名方法。

示例:匿名方法
using System;class Program
{// 定义一个委托类型public delegate void MyDelegate(string message);static void Main(){// 使用匿名方法创建委托实例MyDelegate del = delegate (string message){Console.WriteLine("Anonymous method: " + message);};// 调用委托del("Hello, world!");}
}

 

在这个示例中,匿名方法通过delegate关键字定义,并传递给委托del。然后,调用委托时执行匿名方法。

Lambda表达式

Lambda表达式是一种更简洁的匿名方法语法。它使用=>符号来分隔参数和方法体。

示例:Lambda表达式
using System;
using System.Linq;
using System.Collections.Generic;class Program
{static void Main(){// 使用Lambda表达式创建委托实例Func<int, int, int> add = (a, b) => a + b;// 调用委托int result = add(2, 3);Console.WriteLine("Lambda expression result: " + result);// 另一个示例:使用Lambda表达式查询集合List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };var evenNumbers = numbers.Where(n => n % 2 == 0);foreach (var number in evenNumbers){Console.WriteLine("Even number: " + number);}}
}

 

在这个示例中:

  • Func<int, int, int>是一个内置委托类型,表示接受两个int参数并返回一个int结果的委托。
  • Lambda表达式(a, b) => a + b定义了一个方法体,计算并返回两个整数的和。
  • 使用Lambda表达式n => n % 2 == 0在集合numbers中查询偶数。

匿名方法和Lambda表达式的比较

  • Lambda表达式语法更加简洁和直观,特别是用于简单的操作。
  • 匿名方法在需要复杂逻辑或多行代码时更具可读性。

使用场景

  • 事件处理:简化事件处理程序的定义。
  • LINQ查询:用于编写简洁的查询表达式。
  • 回调:在异步编程和任务中定义回调方法。

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

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

相关文章

【PyTorch][chapter 26][李宏毅深度学习][attention-1]

前言&#xff1a; attention 在自然语言处理&#xff0c;声音处理里面是一个很重要的技巧. attention 要解决的是输入的向量长度不定. 根据输入输出的不同,分为三种场景&#xff1a; 输入N个向量&#xff0c;输出N个向量,这是本章的重点 输入N个向量&#xff0c;输出向量不定 输…

施罗德数列SQL实现

在组合数学中,施罗德数用来描述从(0,0)到(n,n)的格路中,只能使用(1,0)、(0,1)、(1,1)三种移动方式,始终位于对角线下方且不越过对角线的路径数 DECLARE n INT 10 DECLARE i INT DECLARE rst INT DECLARE old INT1CREATE TABLE #rst (i INT ,rst int )INSERT INTO #rst values(…

3-7 使用深度学习解决温度即示数问题

3-7 使用深度学习解决温度即示数问题 直接上代码 %matplotlib inline import matplotlib.pyplot as plt import numpy as np import torch torch.set_printoptions(edgeitems2, linewidth75)设置Jupyter Notebook在单元格中内嵌显示图像&#xff0c;导入所需库并设置PyTorch的…

阿里发布大模型发布图结构长文本处理智能体,超越GPT-4-128k

随着大语言模型的发展&#xff0c;处理长文本的能力成为了一个重要挑战。虽然有许多方法试图解决这个问题&#xff0c;但都存在不同程度的局限性。最近&#xff0c;阿里巴巴的研究团队提出了一个名为GraphReader的新方法&#xff0c;通过将长文本组织成图结构&#xff0c;并利用…

2,区块链、数字货币及其应用场景(react+区块链实战)

2&#xff0c;区块链、数字货币及其应用场景&#xff08;react区块链实战&#xff09; 一、什么是区块链&#xff1f;1 ibloackchain&#xff08;1&#xff09;安装ibloackchain&#xff08;2&#xff09;Blance查询余额&#xff08;3&#xff09;Mine挖矿&#xff08;4&#x…

JavaScript中的拷贝技术探秘:浅拷贝与深拷贝的奥秘

最新技术资源&#xff08;建议收藏&#xff09; https://www.grapecity.com.cn/resources/ 前言 JavaScript中的浅拷贝和深拷贝是非常重要的概念&#xff0c;它们在处理对象和数组时具有不同的作用。在编程中&#xff0c;经常需要复制数据以便进行各种操作&#xff0c;但必须注…

小波与傅里叶变换的对比(Python)

直接上代码&#xff0c;理论可以去知乎看。 #Import necessary libraries %matplotlib inline import numpy as np import matplotlib.pyplot as plt import seaborn as snsimport pywt from scipy.ndimage import gaussian_filter1d from scipy.signal import chirp import m…

基于 sftp 的 NAS (局域网文件存储服务器)

局域网 NAS (文件存储服务器) 的基本功能有: 能够存储文件, 同时能够通过多个设备访问 (上传/下载) 文件. 这些功能通过 sftp 可以实现. sftp 是基于 SSH 的文件传输协议, SSH 全程加密传输, 使用 公钥 认证 (不使用密码/口令), 能够提供很高的安全性. 上文说到, 在 LVM 和 bt…

谷粒商城-个人笔记(集群部署篇三)

前言 ​学习视频&#xff1a;​Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强​学习文档&#xff1a; 谷粒商城-个人笔记(基础篇一)谷粒商城-个人笔记(基础篇二)谷粒商城-个人笔记(基础篇三)谷粒商城-个人笔记(高级篇一)谷粒商城-个…

古建筑倾斜在线监测系统:科技守护历史的创新实践

​ ​​在文化遗产保护的广阔领域中&#xff0c;古建筑的健康监测占据着举足轻重的地位。然而&#xff0c;传统的监测方法往往受限于布线复杂、安装难度大以及对古建筑本体可能造成的伤害等问题。近年来&#xff0c;一种新型的古建筑倾斜在线监测系统应运而生&#xff0c;它…

Halcon 模糊圆边的找圆案例

Halcon 模糊圆边的找圆案例 基本思路 1.将图像转成灰度图像 2.再观察要找到的区域的灰度值变化&#xff0c;找到前景与背景的具体数值。 3.根据找到的前景与背景的具体数值&#xff0c;增强图像对比度。&#xff08;使图像变成黑白图片&#xff09; 4.使用灰度直图工具进行阈值…

用Vue3和Plotly.js绘制交互式3D散点图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 使用 Plotly.js 创建 2D 密度图 应用场景介绍 密度图是一种可视化数据分布的图表&#xff0c;它显示了数据点的密度在不同区域的变化情况。在许多科学和工程领域中&#xff0c;密度图被广泛用于探索和分析数据…

5G(NR) NTN 卫星组网架构

5G(NR) NTN 卫星组网架构 参考 3GPP TR 38.821 5G NTN 技术适用于高轨、低轨等多种星座部署场景&#xff0c;是实现星地网络融合发展的可行技术路线。5G NTN 网络分为用户段、空间段和地面段三部分。其中用户段由各种用户终端组成&#xff0c;包括手持、便携站、嵌入式终端、车…

git撤销/返回到某次提交(idea工具 + gitbush)

不多说废话&#xff0c;直接展示使用。 方法一&#xff1a;使用idea工具进行返回 准备某次过度提交 使用idea打开git log 找到要回去的版本 点击右键选到reset 模式选hard&#xff0c;强制回滚 这个时候本地代码已经回归你指定的版本了。 这个时候再进行强制推送&#xff0c…

Drools开源业务规则引擎(三)- 事件模型(Event Model)

文章目录 Drools开源业务规则引擎&#xff08;三&#xff09;- 事件模型&#xff08;Event Model&#xff09;1.org.kie.api.event2.RuleRuntimeEventManager3.RuleRuntimeEventListener接口说明示例规则文件规则执行日志输出 4.AgentaEventListener接口说明示例监听器实现类My…

09 docker 安装tomcat 详解

目录 一、安装tomcat 1. tomcat镜像的获取 2. docker创建容器实列 3. 访问测试 404错误 4. 解决方案 5. 使用免修改版容器镜像 5.1. 运行实列的创建 5.2. 出现问题及解决&#xff1a; 6. 验证 OK 一、安装tomcat 1. tomcat镜像的获取 docker search tomcat #docker …

SCI二区TOP|蜘蛛黄蜂优化算法(SWO)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2023年&#xff0c;M Abdel-Basset受到蜘蛛黄蜂优化社会行为启发&#xff0c;提出了蜘蛛黄蜂优化算法&#xff08;Spider Wasp Optimizer, SWO&#xff09;。 2.算法原理 2.1算法思想 S…

视频监控技术在食品安全监管中的关键应用

视频监控技术在食品安全监管中的关键应用 1、视频监控技术在食品安全监管中的作用 在食品安全监管中&#xff0c;视频监控技术发挥着不可替代的作用。通过安装视频监控系统&#xff0c;可以实现对食品生产、运输、储存等各个环节的实时监控和录像存储。这不仅有助于监管部门及…

Linux的前世今生

Unix的起源和发展 1969年&#xff0c;AT&T贝尔实验室的Ken Thompson和Dennis Ritchie等人开发了Unix操作系统。Unix的设计理念强调小而简洁的工具&#xff0c;文本流和系统模块化&#xff0c;这些理念后来成为Linux开发的重要基础。1973年&#xff0c;Unix用C语言重新编写…

深度学习-数学基础(四)

深度学习数学基础 数学基础线性代数-标量和向量线性代数-向量运算向量加和向量内积向量夹角余弦值 线性代数-矩阵矩阵加法矩阵乘法矩阵点乘矩阵计算的其他内容 人工智能-矩阵的操作矩阵转置&#xff08;transpose&#xff09;矩阵与向量的转化 线性代数-张量&#xff08;tensor…