iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >C#值类型、引用类型、泛型、集合的表达式树怎么创建
  • 342
分享到

C#值类型、引用类型、泛型、集合的表达式树怎么创建

2023-06-26 07:06:07 342人浏览 八月长安
摘要

这篇文章主要介绍了C#值类型、引用类型、泛型、集合的表达式树怎么创建的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#值类型、引用类型、泛型、集合的表达式树怎么创建文章都会有所收获,下面我们一起来看看吧。一,定

这篇文章主要介绍了C#值类型、引用类型、泛型、集合的表达式树怎么创建的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#值类型、引用类型、泛型、集合的表达式树怎么创建文章都会有所收获,下面我们一起来看看吧。

    一,定义变量

    C# 表达式树中,定义一个变量,使用 ParameterExpression

    创建变量结点的方法有两种,

    Expression.Parameter()Expression.Variable()// 另外,定义一个常量可以使用 Expression.Constant()。

    两种方式都是生成 ParameterExpression 类型 Parameter() 和 Variable() 都具有两个重载。他们创建一个 ParameterExpression节点,该节点可用于标识表达式树中的参数或变量。

    对于使用定义:

    Expression.Variable 用于在块内声明局部变量。

    Expression.Parameter用于声明输入值的参数。

    先看第一种

            public static ParameterExpression Parameter(Type type)        {            return Parameter(type, name: null);        }                        public static ParameterExpression Variable(Type type)        {            return Variable(type, name: null);        }

    从代码来看,没有区别。

    再看看具有两个参数的重载

            public static ParameterExpression Parameter(Type type, string name)        {            Validate(type, allowByRef: true);            bool byref = type.IsByRef;            if (byref)            {                type = type.GetElementType();            }            return ParameterExpression.Make(type, name, byref);        }
            public static ParameterExpression Variable(Type type, string name)        {            Validate(type, allowByRef: false);            return ParameterExpression.Make(type, name, isByRef: false);        }

    如你所见,两者只有一个 allowByRef 出现了区别,Paramter 允许 Ref, Variable 不允许。

    笔者在官方文档和其他作者文章上,都没有找到具体区别是啥,去 stackoverflow 搜索和查看源代码后,确定他们的区别在于 Variable 不能使用 ref 类型。

    从字面意思来看,声明一个变量,应该用Expression.Variable, 函数的传入参数应该使用Expression.Parameter

    无论值类型还是引用类型,都是这样子定义。

    二,访问变量/类型的属性字段和方法

    访问变量或类型的属性,使用

    Expression.Property()

    访问变量/类型的属性或字段,使用

    Expression.PropertyOrField()

    访问变量或类型的方法,使用

    Expression.Call()

    访问属性字段和方法

    Expression.MakeMemberAccess

    他们都返回一个 MemberExpression类型。

    使用上,根据实例化/不实例化,有个小区别,上面说了变量或类型。

    意思是,已经定义的值类型或实例化的引用类型,是变量;

    类型,就是指引用类型,不需要实例化的静态类型或者静态属性字段/方法。

    上面的解释不太严谨,下面示例会慢慢解释。

    1. 访问属性

    使用 Expression.Property() 或 Expression.PropertyOrField()调用属性。

    调用静态类型属性

    Console 是一个静态类型,Console.Title 可以获取编译器程序的实际位置。

                Console.WriteLine(Console.Title);

    使用表达式树表达如下

                MemberExpression member = Expression.Property(null, typeof(Console).GetProperty("Title"));            Expression<Func<string>> lambda = Expression.Lambda<Func<string>>(member);            string result = lambda.Compile()();            Console.WriteLine(result);            Console.ReadKey();

    因为调用的是静态类型的属性,所以第一个参数为空。

    第二个参数是一个 PropertyInfo 类型。

    调用实例属性/字段

    C#代码如下

                List<int> a = new List<int>() { 1, 2, 3 };            int result = a.Count;            Console.WriteLine(result);            Console.ReadKey();

    在表达式树,调用实例的属性

                ParameterExpression a = Expression.Parameter(typeof(List<int>), "a");            MemberExpression member = Expression.Property(a, "Count");            Expression<Func<List<int>, int>> lambda = Expression.Lambda<Func<List<int>, int>>(member, a);            int result = lambda.Compile()(new List<int> { 1, 2, 3 });            Console.WriteLine(result);            Console.ReadKey();

    除了 Expression.Property() ,其他的方式请自行测试,这里不再赘述。

    2. 调用函数

    使用 Expression.Call() 可以调用一个静态类型的函数或者实例的函数。

    调用静态类型的函数

    以 Console 为例,调用 WriteLine() 方法

                Console.WriteLine("调用WriteLine方法");            MethodCallExpression method = Expression.Call(                null,                typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }),                Expression.Constant("调用WriteLine方法"));            Expression<Action> lambda = Expression.Lambda<Action>(method);            lambda.Compile()();            Console.ReadKey();

    Expression.Call() 的重载方法比较多,常用的重载方法是

    public static MethodCallExpression Call(Expression instance, MethodInfo method, params Expression[] arguments)

    因为要调用静态类型的函数,所以第一个 instance 为空(instance英文意思是实例)。

    第二个 method 是要调用的重载方法。

    最后一个 arguments 是传入的参数。

    调用实例的函数

    写一个类

        public class Test    {        public void Print(string info)        {            Console.WriteLine(info);        }    }

    调用实例的 Printf() 方法

                Test test = new Test();            test.Print("打印出来");            Console.ReadKey();

    表达式表达如下

                ParameterExpression a = Expression.Variable(typeof(Test), "test");            MethodCallExpression method = Expression.Call(                a,                typeof(Test).GetMethod("Print", new Type[] { typeof(string) }),                Expression.Constant("打印出来")                );            Expression<Action<Test>> lambda = Expression.Lambda<Action<Test>>(method,a);            lambda.Compile()(new Test());            Console.ReadKey();

    注意的是,Expression.Variable(typeof(Test), "test"); 仅定义了一个变量,还没有初始化/赋值。对于引用类型来说,需要实例化。

    上面的方式,是通过外界实例化传入里面的,后面会说如何在表达式内实例化。

    三,实例化引用类型

    引用类型的实例化,使用 new ,然后选择调用合适的构造函数、设置属性的值。

    那么,根据上面的步骤,我们分开讨论。

    new

    使用 Expression.New()来调用一个类型的构造函数。

    他有五个重载,有两种常用重载:

     public static NewExpression New(ConstructorInfo constructor); public static NewExpression New(Type type);

    依然使用上面的 Test 类型

                NewExpression newA = Expression.New(typeof(Test));

    默认没有参数的构造函数,或者只有一个构造函数,像上面这样调用。

    如果像指定一个构造函数,可以

                NewExpression newA = Expression.New(typeof(Test).GetConstructor(xxxxxx));

    这里就不详细说了。

    给属性赋值

    实例化一个构造函数的同时,可以给属性赋值。

            public static MemberInitExpression MemberInit(NewExpression newExpression, IEnumerable<MemberBinding> bindings);        public static MemberInitExpression MemberInit(NewExpression newExpression, params MemberBinding[] bindings);

    两种重载是一样的。

    我们将 Test 类改成

        public class Test    {        public int sample { get; set; }        public void Print(string info)        {            Console.WriteLine(info);        }    }

    然后

                var binding = Expression.Bind(                typeof(Test).GetMember("sample")[0],                Expression.Constant(10)            );

    创建引用类型

    Expression.MemberInit()

    表示调用构造函数并初始化新对象的一个或多个成员。

    如果实例化一个类,可以使用

                NewExpression newA = Expression.New(typeof(Test));            MemberInitExpression test = Expression.MemberInit(newA,                new List<MemberBinding>() { }                );

    如果要在实例化时给成员赋值

                NewExpression newA = Expression.New(typeof(Test));            // 给 Test 类型的一个成员赋值            var binding = Expression.Bind(                typeof(Test).GetMember("sample")[0],Expression.Constant(10));            MemberInitExpression test = Expression.MemberInit(newA,                new List&lt;MemberBinding&gt;() { binding}                );

    示例

    实例化一个类型,调用构造函数、给成员赋值,示例代码如下

                // 调用构造函数            NewExpression newA = Expression.New(typeof(Test));            // 给 Test 类型的一个成员赋值            var binding = Expression.Bind(                typeof(Test).GetMember("sample")[0], Expression.Constant(10));            // 实例化一个类型            MemberInitExpression test = Expression.MemberInit(newA,                new List<MemberBinding>() { binding }                );            // 调用方法            MethodCallExpression method1 = Expression.Call(                test,                typeof(Test).GetMethod("Print", new Type[] { typeof(string) }),                Expression.Constant("打印出来")                );            // 调用属性            MemberExpression method2 = Expression.Property(test, "sample");            Expression<Action> lambda1 = Expression.Lambda<Action>(method1);            lambda1.Compile()();            Expression<Func<int>> lambda2 = Expression.Lambda<Func<int>>(method2);            int sample = lambda2.Compile()();            Console.WriteLine(sample);            Console.ReadKey();

    四,实例化泛型类型于调用

    将 Test 类,改成这样

        public class Test<T>    {        public void Print<T>(T info)        {            Console.WriteLine(info);        }    }

    Test 类已经是一个泛型类,表达式实例化示例

            static void Main(string[] args)        {            RunExpression<string>();            Console.ReadKey();        }        public static void RunExpression<T>()        {            // 调用构造函数            NewExpression newA = Expression.New(typeof(Test<T>));            // 实例化一个类型            MemberInitExpression test = Expression.MemberInit(newA,                new List<MemberBinding>() { }                );            // 调用方法            MethodCallExpression method = Expression.Call(                test,                typeof(Test<T>).GetMethod("Print").MakeGenericMethod(new Type[] { typeof(T) }),                Expression.Constant("打印出来")                );            Expression<Action> lambda1 = Expression.Lambda<Action>(method);            lambda1.Compile()();            Console.ReadKey();        }

    五,定义集合变量、初始化、添加元素

    集合类型使用 ListInitExpression表示。

    创建集合类型,需要使用到

    ElementInit 表示 IEnumerable集合的单个元素的初始值设定项。

    ListInit 初始化一个集合。

    C# 中,集合都实现了 IEnumerable,集合都具有 Add 扥方法或属性。

    使用 C# 初始化一个集合并且添加元素,可以这样

                List<string> list = new List<string>()            {                "a",                "b"            };            list.Add("666");

    而在表达式树里面,是通过 ElementInit 调用 Add 方法初始化/添加元素的。

    示例

                MethodInfo listAdd = typeof(List<string>).GetMethod("Add");                        ElementInit add1 = Expression.ElementInit(                listAdd,                Expression.Constant("a"),                Expression.Constant("b")                );            // Add("666")            ElementInit add2 = Expression.ElementInit(listAdd, Expression.Constant("666"));

    示例

                MethodInfo listAdd = typeof(List<string>).GetMethod("Add");            ElementInit add1 = Expression.ElementInit(listAdd, Expression.Constant("a"));            ElementInit add2 = Expression.ElementInit(listAdd, Expression.Constant("b"));            ElementInit add3 = Expression.ElementInit(listAdd, Expression.Constant("666"));            NewExpression list = Expression.New(typeof(List<string>));            // 初始化值            ListInitExpression setList = Expression.ListInit(                list,                add1,                add2,                add3                );            // 没啥执行的,就这样看看输出的信息            Console.WriteLine(setList.ToString());            MemberExpression member = Expression.Property(setList, "Count");            Expression<Func<int>> lambda = Expression.Lambda<Func<int>>(member);            int result = lambda.Compile()();            Console.WriteLine(result);            Console.ReadKey();

    关于“C#值类型、引用类型、泛型、集合的表达式树怎么创建”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C#值类型、引用类型、泛型、集合的表达式树怎么创建”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

    --结束END--

    本文标题: C#值类型、引用类型、泛型、集合的表达式树怎么创建

    本文链接: https://www.lsjlt.com/news/307324.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • C#值类型、引用类型、泛型、集合的表达式树怎么创建
      这篇文章主要介绍了C#值类型、引用类型、泛型、集合的表达式树怎么创建的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#值类型、引用类型、泛型、集合的表达式树怎么创建文章都会有所收获,下面我们一起来看看吧。一,定...
      99+
      2023-06-26
    • C#值类型、引用类型、泛型、集合、调用函数的表达式树实践
      目录一,定义变量二,访问变量/类型的属性字段和方法1. 访问属性调用静态类型属性调用实例属性/字段2. 调用函数调用静态类型的函数调用实例的函数三,实例化引用类型new给属性赋值创建...
      99+
      2024-04-02
    • C#基元类型、值类型、引用类型是什么
      这篇文章主要讲解了“C#基元类型、值类型、引用类型是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#基元类型、值类型、引用类型是什么”吧!首先了解下什么是基元类型,基元类型是编译器直接...
      99+
      2023-06-17
    • C#怎么使用泛型集合存储不同类型的对象
      在C#中,您可以使用泛型集合来存储不同类型的对象。为此,您可以使用泛型类List或Dictionary<TKey, TValu...
      99+
      2024-04-09
      C#
    • C#中值类型和引用类型的区别
      一、值类型和引用类型的区别 .NET的类型可以分为两类:值类型和引用类型。这两种类型各有特点,即使它们都继承自System.Object,并且有装箱和拆箱等操作确保两种类型可以方便地...
      99+
      2024-04-02
    • c#引用类型与值类型的区别是什么
      这篇文章主要讲解了“c#引用类型与值类型的区别是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“c#引用类型与值类型的区别是什么”吧!解析:CLR支持两种类型:值类型和引用类型。用Jeff...
      99+
      2023-06-17
    • 使用指向类型参数的指针创建泛型类型的实例
      php小编鱼仔在这篇文章中将介绍如何使用指向类型参数的指针来创建泛型类型的实例。泛型是一种在编程中广泛应用的概念,它允许我们在不指定具体类型的情况下编写通用的代码。在php中,虽然没有...
      99+
      2024-02-09
    • C#程序中怎么使用泛型集合代替非泛型集合
      C#程序中怎么使用泛型集合代替非泛型集合,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。软件开发过程中,不可避免会用到集合,C#中的集合表现为数...
      99+
      2024-04-02
    • C#中引用类型和值类型有什么区别
      在C#中,引用类型和值类型是两种不同的数据类型。 值类型是直接存储在堆栈中的数据,它们保存的是实际的数据值。当值类型的变量被赋值给另...
      99+
      2024-03-07
      C#
    • C#中的值类型与引用类型有什么区别
      在C#中,值类型和引用类型是两种不同的数据类型,它们有以下区别: 存储位置:值类型的变量直接存储在堆栈中,而引用类型的变量存储在...
      99+
      2024-04-03
      C#
    • C#泛型集合实例怎么用
      小编给大家分享一下C#泛型集合实例怎么用,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!C# 泛型集合了解之前我们明白集合是OOP中的一个重要概念,C#中对集合的全面支持更是该语言的精华之一。C# 泛型是C# 2.0中的新增...
      99+
      2023-06-17
    • C#泛型集合类List<T>如何使用
      这篇“C#泛型集合类List<T>如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C#泛型集合类List&...
      99+
      2023-06-30
    • C# 泛型集合类List<T>使用总结
      目录为什么选择使用List,而不是使用Array,或者ArryList去重、交集、并集、差集操作重写Equals() 和 GetHashCode()简单使用C#中List可谓是使用最...
      99+
      2024-04-02
    • C++ lambda 表达式的返回值类型如何定义?
      在 c++++ 中,lambda 表达式的返回值类型通过 ->return-type 指定,允许明确定义 lambda 的返回值。通过指定返回值类型,可以增强代码的可读性并避免编译器自动...
      99+
      2024-04-17
      c++ lambda
    • mysql创建表数据类型怎么用
      在 mysql 中创建表时,需要指定列的数据类型以定义其存储的数据类型和格式。常见数据类型包括整数、浮点数、字符、日期和时间以及布尔类型,选择合适的数据类型影响着数据存储大小、值范围、性...
      99+
      2024-04-22
      mysql
    • javascript引用类型怎么赋值
      小编给大家分享一下javascript引用类型怎么赋值,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!1、说明引用类型的赋值实际上是对象保存在栈区地址指针上的授权值,因此两个变量指向同一个对象,任何操作都会相互影响。从一个变...
      99+
      2023-06-15
    • js中值类型和引用类型的区别是什么
      这篇文章主要介绍“js中值类型和引用类型的区别是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“js中值类型和引用类型的区别是什么”文章能帮助大家解决问题。1.JavaScript中的变量类型有哪...
      99+
      2023-07-02
    • C++引用类型怎么使用
      这篇文章主要介绍“C++引用类型怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C++引用类型怎么使用”文章能帮助大家解决问题。一、C++中的引用类型思考:如何在被调函数中修改主调函数中定义的...
      99+
      2023-07-02
    • python表达式4+0.5值是什么数据类型
      这篇文章主要介绍了python表达式4+0.5值是什么数据类型的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇python表达式4+0.5值是什么数据类型文章都会有所收获,下面我...
      99+
      2024-04-02
    • 怎么用C#表达式树Expression动态创建表达式
      本篇内容介绍了“怎么用C#表达式树Expression动态创建表达式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在一些管理后台中,对数据进...
      99+
      2023-06-22
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作