c# 把一个匿名对象赋值给一个Object类型的变量后,怎么取这个变量? c# dynamic动态类型和匿名类 详解C# 匿名对象(匿名类型)、var、动态类型 dynamic 深入浅析C#中的var和dynamic
比如有一个匿名对象,var result =......Select( a=>new { id=a.id, name=a.name});
然后Object obj = result ;
我怎么从obj 中取出 id和name ?
dynamic a = obj;
var bb = a.id;
var cc = a.name;
如果要重复使用数据模式,那么最可行的做法是重构代码,立刻增加一个模式定义,例如
1
2
3
4
5
|
public class AA { public string id; public string name; } |
编程设计时代码会呈现有很多“层次”,比如说有人甚至说非要
1
2
|
var x = obj; var y = eval( "obj.id" ); |
这种,他非要字符串才“爽”。
编程要尽可能地强类型、按照接口设计代码,一个程序中的反射代码不过也就是万分之一而已,千方百计避免滥用。那么从设计理念上就要保持一种“规范”。
动态语言语法有它的好处,由她的方便性,这个是不可否认的。至于说什么时候该使用动态的特性,让运行时——而非编译时——才出现bug、系统崩溃提示(不怕在用户面前丢脸),那就要靠经验来判断。所以不要轻易滥用动态特性。
c# dynamic动态类型和匿名类
dynamic类型
简单示例
dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写
expando.Id = 1;
expando.Name = "Test";
string json = Utils.ConvertJson.JsonEncode(expando); //输出{Id:1,Name:'Test'}
//动态添加字段
List<string> fieldList = new List<string>() { "Name","Age","Sex"}; //From config or db
dynamic dobj = new System.Dynamic.ExpandoObject();
var dic = (IDictionary<string, object>)dobj;
foreach (var fieldItem in fieldList)
{
dic[fieldItem] = "set "+fieldItem+" value"; /*实现类似js里的 动态添加属性的功能
var obj={};
var field="Id";
eval("obj."+field+"=1");
alert(obj.Id); //1 */
}
var val = dobj.Name; //“set Name value”
var val1=dobj.Age;//”set Age value“
枚举该对象所有成员
foreach (var fieldItem in (IDictionary<String, Object>)dobj)
{
var v = (fieldItem.Key + ": " + fieldItem.Value);
}
匿名类
//var aaaa = new {Id=1,Name="Test"}; //匿名类字段只读不可写
dynamic aaaa = new {Id=1,Name="Test"}; //匿名类字段只读不可写
aaaa.Id = 2; //不可写 报错无法为属性或索引器“<>f__AnonymousType1<int>.Id”赋值 - 它是只读的
dynamic obj = Newtonsoft.Json.JsonConvert.DeserializeObject("{Name:'aa',Sex:'Male',Age:11}");
var name = obj.Name.Value; //aa
原文地址:http://www.cnblogs.com/xuejianxiyang/p/4964739.html
随着C#的发展,该语言内容不断丰富,开发变得更加方便快捷,C# 的锋利尽显无疑。C# 语言从诞生起就是强类型语言,这一性质到今天不曾改变,我想以后也不会变。既然是强类型语言,那编写任一程序均要求满足下面的基本条件:
1、变量声明必须指明其类型
2、变量类型明确后,其类型在Runtime亦不能改变
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public class Student { public string Name { get ; set ; } public int Age { get ; set ; } public string Like { get ; set ; } } static void Main( string [] args) { int a = 10; string s = "abc" ; Student student = new Student(); //下面出现编译错误,变量类型在声明后无法再变更 s = a; student = s; a = 10.1f; } |
然而,在实际开发中我们经常面临如下几种常见问题:
1、在一个较大的程序程序中,只有一处或很少几处(不超过3处)需要用到 某个或某些类型(如上 Student),其他地方不再需要这些类型。单独声明一个Student类型,所需代码量,可能超过使用该类型时的代码量,投入产出比不划算。
2、在一处程序中,只需要某种类型对象的部分属性或方法参与运算。在这种情况下将该类型对象临时转换为程序所需的部分属性和方法的对象,可使程序更加精简。
3、其他情况........我暂未留意到......欢迎补充........
上面这些 C# 实际开发中常见问题,在 JavaScript 开发中有着比较好的解决方案,如下:
1
2
3
4
5
6
|
//在此处js中需要模拟一个学生对象 student = { "name" : "张三" , "age" :20, "like" : "LOL" }; //在此处js中需要模拟一个老师对象 teacher = { "name" : "李老师" , "like" : "没收学生手机,自己LOL" }; //此处需要将学生student转换成只有name和age的对象 person = { "name" :student.name, "age" :student.age}; |
如果你不熟悉上面的js语法,你可以去百度搜索 “json语法”,告诉你很简单哦(而且很重要)。
匿名对象(匿名类型)
因此C#在3.0版本中吸收了JavaScript脚本语言的这种语法优点,对C#做了相应升级使其也支持这种语法形式(C#依然是强类型语言)。示例代码如下:
1
2
3
4
|
static void Main( string [] args) { new {Name= "张三" ,Age=20,Like= "LOL" }; } |
上面的C#代码 通过new关键字告诉编译器要创建一个对象,该对象具有Name,Age,Like三个属性,=后为属性对应的值。如此我们避开了“创建一个对象首先要有该对象类型的约束”,因此在开发过程中对于使用较少的类型我们无需再创建单独的类了,上面提到的问题1被解决。
现在创建出来的对象没指定具体类型,因此称为匿名对象。
Var登场
现在要使用匿名对象,则需要使用变量引用它。虽然我们在创建时没有指定对象的类型,但编译器会在编译过程中帮我们创建一个具有相关属性和方法的类型。此时编译出的类型名称是随机生成的,因此变量类型无法确定。示例如下:
1
2
3
4
5
6
|
static void Main( string [] args) { //XXX为类型声明 //x为引用变量 XXX x = new {Name= "张三" ,Age=20,Like= "LOL" }; } |
虽然我们不知道编译器生成的类型名称,但我们可 让编译器自己根据编译的结果来推断变量类型。此时var关键字便发挥作用了:
1
2
3
4
|
static void Main( string [] args) { var x = new {Name= "张三" ,Age=20,Like= "LOL" }; } |
var 关键字说明 x 的类型由赋于的值来决定(推定),并能根据编译器推定给出智能提示,如下图:
var使用注意事项:
1、var 仅能声明方法内的局部变量
2、var 声明的变量在被赋值后类型即确定下了,后续程序中不能在赋其他类型的值
3、var x = new object() 没有意义,不要写这样的代码...............
现在有匿名对象和var推断类型的支持,我们就能处理上面提到的问题2。示例代码如下:
1
2
3
4
5
|
static void Main( string [] args) { var x = new { Name = "张三" , Age = 20, Like = "LOL" }; var s = new { Name = x.Name, Age = x.Age }; } |
上面仅为示例,如果你熟悉Linq或Entity Framework,那问题2对应的用法将是铺天盖地的.......
动态类型 dynamic 出场
对于匿名类型的使用一般局限于方法的局部,可理解为:随用随定义,用完就消失。有如下情况应该怎么办?
1
2
3
4
5
6
7
8
9
|
static void Main( string [] args) { var x = GetObject(); } private static XXX GetObject() { return new { Name = "张三" , Age = 20, Like = "LOL" }; } |
通过GetObject方法返回一个匿名对象,所以方法返回值 类型名称无法确定,此处暂时用XXX代替。在这种情况下返回的类型不确定,可以使用 dynamic 来指明。如下:
1
2
3
4
5
6
7
8
9
|
static void Main( string [] args) { var x = GetObject(); Console.WriteLine(x.Name); } private static dynamic GetObject() { return new { Name = "张三" , Age = 20, Like = "LOL" }; } |
此时方法不会出现语法错误,程序可以成功编译并执行。那么 dynamic 到底做了什么,可以使上面的程序成功编译呢?
dynamic的作用:
1、dynamic 表示动态类型,动态类型的含义就是 程序编写、编译阶段 类型不确定,在Runtime时再通过反射机制确定相关对象的属性或方法。因此编写阶段不会进行语法检测。
2、dynamic 可用来声明 字段、属性、方法参数、方法返回值
3、dynamic 不支持智能提示,因为你写代码时 dynamic 是什么没法知晓(反射)
dynamic 声明的变量,可理解为 object 类型变量。所以给dynamic变量赋任何类型值都正确,但在使用变量来取得某个属性值或调用某方法时(此时程序肯定处于Runtime状态),CLR会检查(反射)所调用的属性或方法是否存在,不存在报运行时异常。
dynamic在 Asp.net Mvc web开发中处处使用,虽然看上去很复杂,本质就上面所说内容。
说明:
var 和 dynamic 看似功能类似,但它们是不同的:
var | dynamic | |
声明字段 | × | √ |
局部变量 | √ | √ |
方法参数类型 | × | √ |
方法返回值类型 | × | √ |
总结
以上所述是小编给大家介绍的C# 匿名对象(匿名类型)、var、动态类型 dynamic,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
您可能感兴趣的文章:
原文链接:http://www.cnblogs.com/dw039/p/7472119.html
这篇文章给大家介绍了C#中的var和dynamic的相关知识,var和dynamic的本质区别是类型判断的时间不同,前者是编译时,后者是运行时。具体内容详情大家通过本文学习下吧
在理解var
和dynamic
关键字之前,让我们先了解一下编程语言的类别。
C#中有两类编程语言:
- 静态类型语言类别
- 动态语言类别
静态类型语言
静态类型语言也被称为强类型语言。所谓强类型语言,通俗的讲,就是在编译过程中执行类型检查的语言。我们举个简单的例子,比如我们知道一个方法的返回类型,但是如果返回类型过于复杂,那么我推荐你使用var
。但是,当你明确知道返回类型时,或者返回的只是简单类型,那么我推荐你直接使用该数据类型来声明方法返回类型,就像平时我们经常用string
、int
、bool
等修饰符声明返回类型一样。
接下来让我们来了解C#中的var
关键字。
var
关键字是定义数据类型的间接方式
当你定义特定类型的var
时:
string str = "Test";
这种写法被称为显式类型的声明,也被称为直接声明。
当你使用var
关键字定义一个变量时:
var str = "Test";
这被称为隐式类型声明或间接类型声明。
一般情况下,编译器会在编译过程中验证数据,并在编译过程中创建适当的类型。在此实例中,编译器将检查Test
,并在生成IL代码时将var
关键字替换为字符串。
var
关键字在编译时静态的定义数据类型,而不是在运行时,即:一旦定义了数据类型,它将不会在运行时更改。
让我们看下面的例子:
var str = "Test";str = 123;
生成这个应用程序,如下图所示,将在str = 123
处的隐式转换抛出编译错误
如果将鼠标移动到第一行的str
上,实际上是可以获得局部变量字符串str
的值,如下图所示
我们可以通过使用ILDasm.exe打开这个exe/dll来验证这个结果。
何时使用var
对于像int
、double
、string
等简单数据类型,我们最好使用特定的数据类型来声明变量,以免让事情变得复杂。但当你创建了一个很大的类,那么为了方便创建对象,你最好使用var关键字。还有一种约定俗成的习惯,当我们使用LINQ
或Anonymous
类型时,必须使用var
关键字。
动态类型语言
动态类型语言是指在运行时执行类型检查的语言。如果您不知道您将获得或需要分配的值的类型,则在此情况下,类型是在运行时定义的。让我们看看下面的例子。
1
2
3
4
5
6
|
class Program { static void Main(string[] args) { dynamic str = "Test" ; } } |
现在,如果您输入str.
,那么您将无法获得任何智能提示,如下图所示。
此例中,在为str
分配值之后,如果执行一些数学运算,它不会给出任何错误信息。
1
2
3
4
5
6
7
|
class Program { static void Main(string[] args) { dynamic str = "Test" ; str++; } } |
很明显,现在就算我生成应用程序,也不会有错误产生,应用程序也会成功生成:
但是,如果你运行这个应用程序,对不起,VS会给你如下所示的运行时错误:
dynamic
关键字内部使用反射,感兴趣的童鞋可以自行研究一下。
小结
var
和dynamic
关键字之间的主要区别在于绑定时间不一样:var
是早期绑定,dynamic
绑定则会在运行时进行。
var
实际上是编译器抛给我们的语法糖,一旦被编译,编译器就会自动匹配var
变量的实际类型,并用实际类型来替换该变量的声明,等同于我们在编码时使用了实际类型声明。而dynamic
被编译后是一个Object
类型,编译器编译时不会对dynamic
进行类型检查。
.Net 4.0之前的运行时的动态调用一般是通过反射来实现,但是反射的代码的可读性不高。.Net 4.0之后使用dynamic
就好得多,因为dynamic
是一种静态类型,完全可以像其它类型一样的声明和调用,而不用写反射相关的代码。
合理的运用dynamic
可以让你的代码更加的简洁,而且比直接使用反射性能更好(反射没有优化处理的前提),因为dynamic
是基于DLR
,第一次运行后会缓存起来。其实有心的同学会发现.net的类库里面很多地方都用了dynamic
这个东西,例如:mvc
中的ViewBag
就是一个很好的例子。一般情况下,如果开发者不知道方法和方法的返回类型是否公开,请使用dynamic
关键字。
补充:C# var和dynamic的用法和理解
var和dynamic的本质区别是类型判断的时间不同,前者是编译时,后者是运行时。
1.var在声明变量方面简化语法(只能是局部变量),在编译时交给编译器推断。
2.dynamic也是为简化语法而生的,它的类型推断是交给系统来执行的(运行时推断类型)。
3.var不能用于字段、参数等,而dynamic则可以。
4.var在初始化的时候就确定了类型。
5.dynamic可以用于方法字段、参数、返回值以及泛型参数,把动态发挥的淋漓尽致。
6.dynamic在反射方面做的可以,只是我自己没有尝试过。
7.var是C# 3.0的产物,dynamic是C# 4.0的产物。
最后还得关心一下效率问题:
越底层的效率越高
可以说是 传统强类型 >= var > dynamic,所以用dynamic的时候还得考虑性能和效率!
总结
以上所述是小编给大家介绍的C#中的var和dynamic ,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!
您可能感兴趣的文章:
原文链接:http://www.cnblogs.com/yayazi/p/8998610.html
c# 把一个匿名对象赋值给一个Object类型的变量后,怎么取这个变量? c# dynamic动态类型和匿名类 详解C# 匿名对象(匿名类型)、var、动态类型 dynamic 深入浅析C#中的var和dynamic的更多相关文章
- Struts2-整理笔记(二)常量配置、动态方法调用、Action类详解
1.修改struts2常量配置(3种) 第一种 在str/struts.xml中添加constant标签 <struts> <!-- 如果使用使用动态方法调用和include冲突 - ...
- 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解
数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...
- JDK中Unsafe类详解
Java中Unsafe类详解 在openjdk8下看Unsafe源码 浅析Java中的原子操作 Java并发编程之LockSupport http://hg.openjdk.java.net/jdk7 ...
- Java精通并发-自旋对于synchronized关键字的底层意义与价值分析以及互斥锁属性详解与Monitor对象特性解说【纯理论】
自旋对于synchronized关键字的底层意义与价值分析: 对于synchronized关键字的底层意义和价值分析,下面用纯理论的方式来对它进行阐述,自旋这个概念就会应运而生,还是很重要的,下面阐述 ...
- javaCV开发详解之12:视频转apng动态图片实现,支持透明通道,也支持摄像机、桌面屏幕、流媒体等视频源转apng动态图
wjavaCV系列文章: javacv开发详解之1:调用本机摄像头视频 javaCV开发详解之2:推流器实现,推本地摄像头视频到流媒体服务器以及摄像头录制视频功能实现(基于javaCV-FFMPEG. ...
- 【详细解析】MySQL索引详解( 索引概念、6大索引类型、key 和 index 的区别、其他索引方式)
[详细解析]MySQL索引详解( 索引概念.6大索引类型.key 和 index 的区别.其他索引方式) MySQL索引的概念: 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分 ...
- Java中dimension类详解
Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788
- var和dynamic的应用 var、动态类型 dynamic 深入浅析C#中的var和dynamic ----demo
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 【原创教程】JavaScript详解之语法和对象
JavaScript的好的想法:函数.弱类型.动态对象和一个富有表现力的对象字面量表示法. JavaScript的坏的想法:基于全局变量的编程模型. 好了,不管他是好的还是坏的,都是我的最爱,下面 ...
随机推荐
- _vimrc配置
set nocompatible set encoding=utf8 set guioptions-=T set number set guifont=consolas:h12 source $VIM ...
- LCIS 最长上升公共子序列问题
首先点名一个串叫 L1,另一个叫L2. 明显的是一个DP,那么我们来探讨下如何求得答案. 朴素的算法 首先我们定义状态$dp[ i ][ j ]$表示L1中前i个与L2中前j个的最长公共上升子序列. ...
- InnoDB INFORMATION_SCHEMA Metrics Table
InnoDB INFORMATION_SCHEMA Metrics Table INNODB_METRICS表将所有InnoDB性能和资源相关计数器合并到一个INFORMATION_SCHEMA表中. ...
- debian swoole环境
debian 9.8 #目录 /lnmp/soure #软件下载位置 /lnmp/data #测试程序位置 安装php-7.3.3 #卸载apt安装的 apt-get autoremove php7* ...
- LeetCode (32) Longest Valid Parentheses
题目 Given a string containing just the characters '(' and ')', find the length of the longest valid ( ...
- 【HDU 3037】Saving Beans(卢卡斯模板)
Problem Description Although winter is far away, squirrels have to work day and night to save beans. ...
- .NET中的缓存实现
软件开发中最常用的模式之一是缓存,这是一个简单但非常有效的概念,想法是重用操作结果,执行繁重的操作时,我们会将结果保存在缓存容器中,下次我们需要该结果时,我们将从缓存容器中取出它,而不是再次执行繁重的 ...
- react native 标签出错.
这种错误为标签错误,没办法,你只能往标签上找了,但不一定是<Text></Text>,我是在<TextInput></TextInput>上出错的,多了 ...
- Python编译错误总结
1.TypeError: object() takes no parameters 如果你出现了这个报错,请检查你的__init__函数名或者其定义有没有写错.一般是把__init__写成了__int ...
- FZU-2147-2147 A-B Game,规律题。。
Problem 2147 A-B Game Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description Fat brother ...