首页 > 结构struct(值类型)在实际应用要注意的二点:

结构struct(值类型)在实际应用要注意的二点:

.Net中的数据类型大致可以分为二类:一类是值类型,一类是引用类型;结构(struct)是值类型,从性能上考虑值类型更有优势(关于值类型与引用类型的详细讨论不在本文范围内,大家可以去查阅相关资料).对于一些特定场合:比如仅需要存储数据,不需要体现具体方法的时候,建议大家用struct来代替class,但在使用过程中,有几个容易被忽视的细节.

1.使用struct存储数据做为数据源,与数据显示控件绑定时:

代码如下:

ContractedBlock.gifExpandedBlockStart.gifCode

protected void Page_Load(object sender, EventArgs e)

        {

            List
<MyStruct3> _list = new List<MyStruct3>();

            _list.Add(
new MyStruct3() { Name = "abc", Value = "123" });

            _list.Add(
new MyStruct3() { Name = "cde", Value = "345" });



            
this.Repeater1.DataSource = _list;

            
this.Repeater1.DataBind();

            

        }



 
public struct MyStruct3

        {

            
public string Name;

            
public string Value;



        }

 

前端aspx关键代码:

ContractedBlock.gifExpandedBlockStart.gifCode

<asp:Repeater ID="Repeater1" runat="server">

        
<ItemTemplate>

            
<%Eval("Name"%><br/>;

        
ItemTemplate>

    
asp:Repeater>

 

编译时一切正常,但是运行后,报类似如下错误:

DataBinding:“Test._Default+MyStruct3”不包含名为“Name”的属性

咋整?把MyStruct3的定义改成这样:

ContractedBlock.gifExpandedBlockStart.gifCode

public struct MyStruct3

        {

            
public string Name{ set;get;}

            
public string Value { setget; }



        }



即:我们把字段(Field)改成属性(property),再次运行,一切OK (应该是跟<%# Eval(...)%>采用反射机制有关)

2.结构的构造函数问题

看如下代码

ContractedBlock.gifExpandedBlockStart.gifCode

public struct MyStruct {

            
private string _name;

            
private string _value;



            
public string Name {

                
set { _name = value; }

                
get { return _name; }

            }



            
public string Value

            {

                
set { _value = value; }

                
get { return _value; }

            }



            
public MyStruct(string pName, string pValue) 

            {

                _name 
= pName;

                _value 
= pValue;

            }

        }

 

一切跟在Class中写的一样,没什么特别的,但是我们改成下面的写法:

ContractedBlock.gifExpandedBlockStart.gifCode

public struct MyStruct

        {

            
public string Name { setget; }

            
public string Value { setget; }



            
public MyStruct(string pName, string pValue) 

            {

                Name 
= pName;

                Value 
= pValue;               

            }

        }

即利用c#3.0的自动属性,简化了一下代码,这次编译时vs却提示有错:

"错误 在控制返回到调用程序之前,自动实现的属性“Test._Default.MyStruct2.Value”的支持字段必须完全赋值。请考虑从构造函数初始值设定项中调用默认构造函数。 "

"在给“this”对象的所有字段赋值之前,无法使用该对象"

究其原因,我们用Reflector看下编译器是如何处理"自动属性"的,先把结构改成普通的类(目的是让编译先通过,好观察最终生成的代码

ContractedBlock.gifExpandedBlockStart.gifCode

 public class MyClass

        {

            
public string Name{ set;get;}

            
public string Value { setget; }



            
public MyClass(string pName, string pValue) 

            {

                Name 
= pName;

                Value 
= pValue;

            }



        }

用Reflector反编译成C# 1.0后,代码如下:

ContractedBlock.gifExpandedBlockStart.gifCode

public class MyClass

{

    
// Fields

    [CompilerGenerated]

    
private string <Name>k__BackingField;

    [CompilerGenerated]

    
private string <Value>k__BackingField;



    
// Methods

    public MyClass(string pName, string pValue)

    {

        
base..ctor();

        this.Name =
 pName;

        this.Value =
 pValue;

        
return;

    }



    
// Properties

    public string Name

    {

        [CompilerGenerated]

        
get

        {

            
string str;

            str 
= this.<Name>k__BackingField;

        Label_0009:

            
return str;

        }

        [CompilerGenerated]

        
set

        {

            
this.<Name>k__BackingField = value;

            
return;

        }

    }



    
public string Value

    {

        [CompilerGenerated]

        
get

        {

            
string str;

            str 
= this.<Value>k__BackingField;

        Label_0009:

            
return str;

        }

        [CompilerGenerated]

        
set

        {

            
this.<Value>k__BackingField = value;

            
return;

        }

    }

}

 

观察一下构造函数,变成了

...

base..ctor();

this.Name = pName;

...

关键就在这里:对于类来讲,并不要求在访问类的实例之前对所有成员赋值,所以这里引用this是合法的;而值类型要求在使用前必须对所有成员赋值,所以值类型如果在构造函数中直接给自动属性赋值,这里this代表的就是结构本身,而在此之前自动生成的二个私有成员private string k__BackingField和private string k__BackingField还没赋值,因此报错也就是合情合理了

更多相关:

  • importjava.security.SecureRandom;importjavax.crypto.Cipher;importjavax.crypto.SecretKey;importjavax.crypto.SecretKeyFactory;importjavax.crypto.spec.DESKeySpec;//结果与DES算...

  • 题目:替换空格 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 输入:s = "We are happy." 输出:"We%20are%20happy." 限制: 0 <= s 的长度 <= 10000 解题: 时间复杂度:O(n) 空间复杂度:O(n) class Solution { public:s...

  • 在C++11标准库中,string.h已经添加了to_string方法,方便从其他类型(如整形)快速转换成字面值。 例如: for (size_t i = 0; i < texArrSize; i++)RTX_Shader.SetInt(string("TexArr[") + to_string(i) + "]", 7 + i);...

  • Ubuntu 14.04安装并升级之后,变成楷体字体非常难看,我昨天搞了一晚上,终于理了个头绪,这里整理一下。 经过网上调研,大家的一致看法是,使用开源字体库文泉驿的微黑字体效果比较理想,甚至效果不输windows平台的雅黑字体。下面我打算微黑来美化Ubuntu 14.04. 1.安装文泉驿微黑字体库 sudo aptitude...

  • 使用string时发现了一些坑。 我们知道stl 容器并不是线程安全的,所以在使用它们的过程中往往需要一些同步机制来保证并发场景下的同步更新。 应该踩的坑还是一个不拉的踩了进去,所以还是记录一下吧。 string作为一个容器,随着我们的append 或者 针对string的+ 操作都会让string内部的数据域动态增加,而动态增加的...

  • 在.Net Framework中,配置文件一般采用的是XML格式的,.NET Framework提供了专门的ConfigurationManager来读取配置文件的内容,.net core中推荐使用json格式的配置文件,那么在.net core中该如何读取json文件呢?1、在Startup类中读取json配置文件1、使用Confi...

  •   1 public class FrameSubject extends JFrame {   2    3   …………..   4    5   //因为无法使用多重继承,这儿就只能使用对象组合的方式来引入一个   6    7   //java.util.Observerable对象了。   8    9   DateSub...

  • 本案例主要说明如何使用NSwag 工具使用桌面工具快速生成c# 客户端代码、快速的访问Web Api。 NSwagStudio 下载地址 比较强大、可以生成TypeScript、WebApi Controller、CSharp Client  1、运行WebApi项目  URL http://yourserver/swagger 然后...

  •   在绑定完Action的所有参数后,WebAPI并不会马上执行该方法,而要对参数进行验证,以保证输入的合法性.   ModelState 在ApiController中一个ModelState属性用来获取参数验证结果.   public abstract class ApiController : IHttpController,...

  • 1# 引用  C:AVEVAMarineOH12.1.SP4Aveva.ApplicationFramework.dll C:AVEVAMarineOH12.1.SP4Aveva.ApplicationFramework.Presentation.dll 2# 引用命名空间, using Aveva.Applicati...

  • 引言 在这个-SLAM建图和导航仿真实例-项目中,主要分为三个部分,分别是 (一)模型构建(二)根据已知地图进行定位和导航(三)使用RTAB-MAP进行建图和导航 该项目的slam_bot已经上传我的Github。 这是第三部分,完成效果如下 图1 建图和导航 三、使用RTAB-Map进行建图和导航 1. rtab...

  • 引言 在这个-SLAM建图和导航仿真实例-项目中,主要分为三个部分,分别是 (一)模型构建(二)根据已知地图进行定位和导航(三)使用RTAB-MAP进行建图和导航 该项目的slam_bot已经上传我的Github。 由于之前的虚拟机性能限制,我在这个项目中使用了新的ubantu 16.04环境,虚拟机配置 内存 8GCPU...

  • [{name:1},{name:2}].forEach((v,i,ar) => {console.log(v,i,ar)});//基础遍历[{name:1},{name:2}].map((v) => v.name);//[1,2]返回对象数组中指定字段值的一位数组(不改变原始数组)[{name:1},{name:2},{name:3}...

  • 体验内容 使用gmapping方法利用turtlebot底盘移动信息和激光雷达数据进行建图。 1. 安装一些依赖包 sudo apt-get install ros-melodic-move-base* sudo apt-get install ros-melodic-map-server* sudo apt-get insta...

  • 前言 我们知道Java/Python这种语言能够很好得 支持反射。反射机制 就是一种用户输入的字符串到对应实现方法的映射,比如http接口中 用户传入了url,我们需要调用该url对应的方法/函数对象 从而做出对应的操作。 而C++ 并没有友好得支持这样的操作,而最近工作中需要通过C++实现http接口,这个过程想要代码实现得优雅...