C#值类型、引用类型、泛型、集合、调用函数的表达式树实践

下面我将对这五个主题分别进行详细的介绍和示例说明。

C#值类型和引用类型

在C#中,变量可以分为值类型和引用类型。值类型存储的是实际的值,而引用类型存储的是内存地址。值类型包括整型、浮点型、字符型、布尔型等,而引用类型包括类、数组、委托等等。

在实际开发中,我们通常需要对值类型和引用类型进行区分。下面是一个简单的示例代码,展示了值类型和引用类型的区别:

int i = 10; // 值类型变量
int j = i;  // 变量的值被赋值给新变量
j = 20;     // 修改新变量的值,不影响原变量的值
Console.WriteLine("i = {0}, j = {1}", i, j);    // 输出:i = 10, j = 20

List<int> list1 = new List<int>() { 1, 2, 3 }; // 引用类型变量,创建一个整型列表
List<int> list2 = list1;                       // 将列表的引用赋值给新变量
list2.Add(4);                                  // 向新列表中添加一个元素
Console.WriteLine("list1 = {0}, list2 = {1}", string.Join(",", list1), string.Join(",", list2));    // 输出:list1 = 1,2,3,4, list2 = 1,2,3,4

从上述示例代码可知,值类型的变量在被赋值时是进行拷贝的,而引用类型的变量在被赋值时是共享内存地址的。因此,在修改引用类型变量时,会影响所有指向该内存地址的变量。

泛型

泛型是C#中非常重要的一个概念。它将类型参数化,使得类、方法和接口可以用于多种不同类型的数据。泛型代码具有高复用性,可以大幅减少代码的重复编写。

下面是一个简单的示例代码,展示了泛型类型的使用:

public class GenericStack<T>
{
    private List<T> _items = new List<T>();

    public void Push(T item)
    {
        _items.Add(item);
    }

    public T Pop()
    {
        if (_items.Count == 0)
        {
            throw new InvalidOperationException("The stack is empty.");
        }

        T item = _items[_items.Count - 1];
        _items.RemoveAt(_items.Count - 1);
        return item;
    }
}

GenericStack<int> stack = new GenericStack<int>();
stack.Push(1);
stack.Push(2);
stack.Push(3);
Console.WriteLine(stack.Pop());    // 输出:3
Console.WriteLine(stack.Pop());    // 输出:2
Console.WriteLine(stack.Pop());    // 输出:1

在上述示例代码中,我们定义了一个泛型类型 GenericStack<T>,它实现了栈的基本操作 PushPop。通过在声明变量时指定类型参数,可以创建一个 int 类型的栈。

集合

C#中的集合是一组有序的、通常是可变的元素的数据结构。它们是用来存储和操作数据的常见方法,比如列表、集合、散列表等。

下面是一个简单的示例代码,展示了使用集合来操作数据的方法:

List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };  // 创建整型列表
numbers.Add(6);     // 向列表中添加一个元素
Console.WriteLine(numbers.Count);    // 输出:6

HashSet<int> set = new HashSet<int>() { 1, 2, 3, 4, 5 }; // 创建哈希集合
set.Add(6);     // 向哈希集合中添加一个元素
Console.WriteLine(set.Count);    // 输出:6

Dictionary<string, int> dict = new Dictionary<string, int>();
// 创建字典
dict.Add("apple", 1);
dict.Add("orange", 2);
dict.Add("banana", 3);
Console.WriteLine(dict["orange"]);    // 输出:2

在上述示例代码中,我们使用了三种不同的集合类型:列表 List、哈希集合 HashSet 和字典 Dictionary。它们分别提供了不同的操作方法,可以满足不同的使用场景。

调用函数的表达式树实践

表达式树是C#中非常有用的一个特性。它允许我们以编程方式创建和操作代码中的表达式。通过表达式树,我们可以将函数调用封装到一个表达式中,然后在运行时动态调用该函数。

下面是一个简单的示例代码,展示了使用表达式树调用函数的方法:

// 声明一个带参数的函数
int Add(int a, int b)
{
    return a + b;
}

// 创建表达式
ParameterExpression x = Expression.Parameter(typeof(int), "x");
ParameterExpression y = Expression.Parameter(typeof(int), "y");
BinaryExpression body = Expression.Add(x, y);
Expression<Func<int, int, int>> add = Expression.Lambda<Func<int, int, int>>(body, x, y);

// 编译表达式并调用函数
int result = add.Compile()(1, 2);
Console.WriteLine(result);    // 输出:3

在上述示例代码中,我们定义了一个 Add 函数,它接受两个整型参数并返回它们的和。然后,我们通过表达式树创建了一个调用该函数的表达式,编译表达式并最终调用该函数。

另一个示例代码(来源自微软官方文档),使用表达式树实现了一个比较器,用于将一个字符串列表按长度排序:

List<string> list = new List<string> { "apple", "banana", "cherry", "date" };

// 创建表达式
ParameterExpression parameter = Expression.Parameter(typeof(string), "x");
Expression<Func<string, int>> selector = Expression.Lambda<Func<string, int>>(
    Expression.Property(parameter, "Length"), parameter);
var comparerExpr = typeof(Comparer<>)
    .MakeGenericType(typeof(int))
    .GetProperty("Default", BindingFlags.Static | BindingFlags.Public)
    .GetMethod
    .ReturnType
    .GetMethod("Create", new[] { typeof(Func<,>).MakeGenericType(typeof(int), typeof(int)) })
    .Invoke(null, new object[] { selector });

// 使用表达式排序列表
list.Sort((IComparer<string>)comparerExpr);
Console.WriteLine(string.Join(",", list));    // 输出:date,apple,cherry,banana

在上述示例代码中,我们通过表达式树创建了一个比较器,并将该比较器用于对字符串列表按长度排序。虽然这个过程比较复杂,但它展示了表达式树的一个非常有用的功能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#值类型、引用类型、泛型、集合、调用函数的表达式树实践 - Python技术站

(0)
上一篇 2023年6月1日
下一篇 2023年6月1日

相关文章

  • C#泛型的逆变协变之个人理解

    下面是关于C#泛型的逆变协变的个人理解和相关示例: 什么是泛型逆变和协变? 在C#中,泛型指的是具有参数化类型的类和方法。逆变和协变是泛型中的一种特殊的概念,它们分别指泛型类型参数的赋值方式和约束条件。 泛型逆变(contravariance)指的是泛型类、泛型委托等类型参数的类型参数能够赋值给其父类型参数,或者其父类型参数的类型参数(即父类型的类型参数)能…

    C# 2023年5月14日
    00
  • C#12预览版释出,新功能一览

    概述 C#是微软开发的一种流行的编程语言,广泛用于开发桌面,Web和移动应用程序。在每个新版本中,C# 都会带来令人兴奋的功能和改进,使其更强大、更具表现力和更高效。C# 的最新版本是2022年发布的 C#11,它引入了一系列新功能,例如abstract 和 virtual 引入到静态方法中、泛型 attribute等。现在,微软已经在开发下一个版本的C#,…

    C# 2023年4月19日
    00
  • Unity实现物体跟随鼠标移动

    下面是Unity实现物体跟随鼠标移动的完整攻略。 实现方式 我们可以通过以下几个步骤来实现物体跟随鼠标的移动: 首先,需要给物体添加鼠标拖拽事件(需要在 Update 函数中检测鼠标位置)。 然后,在鼠标按下时,计算出鼠标在屏幕上的位置与物体在场景中的位置的距离差(即偏移量)。 在鼠标移动时,通过计算鼠标在屏幕上的位置与之前计算的偏移量,可以得出物体应该被移…

    C# 2023年6月3日
    00
  • 常用的在数据库中建立无限级树形菜单的asp.net代码

    建立无限级树形菜单是Web开发的常见需求之一。在ASP.NET框架下,我们可以使用数据库的递归查询,加上C#语言的代码逻辑来实现这个功能。下面是需要遵循的步骤和示例说明: 第一步:建立数据库表 应该建立一个名为Menus的表,包含以下字段: Id(菜单ID,主键,自增) Name(菜单名,varchar类型) ParentId(父菜单ID,int类型) 字段…

    C# 2023年5月31日
    00
  • WPF如何利用附加属性修改ShowGridLines效果详解

    下面是详细的攻略: 什么是WPF附加属性? WPF附加属性是一种特殊的属性,在WPF控件中可用。它允许你指定控件的属性,作用于其它控件,与父控件或者与容器进行交互。在XAML代码中,附加属性使用特殊的语法来定义:使用父控件名称作为前缀,并用一个“.”隔开,后面跟着属性名称。例如,Grid.Row=”1″中的“Row”是一个附加属性,作用于Grid实例,而非R…

    C# 2023年6月6日
    00
  • Unity3D获取当前键盘按键及Unity3D鼠标、键盘的基本操作

    Unity3D获取当前键盘按键: Unity3D中获取当前键盘按键可以通过Input.GetKey(),Input.GetKeyDown(),Input.GetKeyUp()三个函数来实现。 其中,Input.GetKeyDown()用于检测用户是否按下某个键,如果是则返回true,否则返回false。而Input.GetKeyUp()用于检测用户是否松开某…

    C# 2023年6月3日
    00
  • 浅析C#中静态方法和非静态方法的区别

    接下来我将为您详细讲解“浅析C#中静态方法和非静态方法的区别”。 什么是C#中的静态方法和非静态方法 在C#中,静态方法和非静态方法是常见的两种方法类型。静态方法是指在类中定义的方法,该方法不需要实例化该类的对象就可以直接调用。而非静态方法则是需要实例化对象后才能被调用的方法。 具体来说,静态方法是使用 static 关键字定义的方法,而非静态方法则不使用 …

    C# 2023年6月7日
    00
  • ASP.NET Core中使用令牌桶限流的实现

    ASP.NET Core中使用令牌桶限流的实现 在 ASP.NET Core 中,令牌桶算法是一种常用的限流算法。本攻略将详细介绍在 ASP.NET Core 中使用令牌桶算法实现限流的方法,并提供多个示例说明。 步骤一:安装 NuGet 包 在 ASP.NET Core 中,可以使用以下命令安装 NuGet 包: dotnet add package As…

    C# 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部