Why are C# structs immutable?
Compiler Error CS1612 Cannot modify the return value of 'expression' because it is not a variable
class Transform
{
public Point p { get; set; } public Point p2;
public void ShowV()
{
Console.WriteLine(p.X + "..." + p.Y);
}
} [Test]
public void TestChuck()
{
Transform t = new Transform();
t.p.X = ;
t.p2.X = ;
t.ShowV();
Console.Read();
}
t.p = new Point(); 这个可以,set可以工作。 但是get出来的是value
Why are C# structs immutable?
问题
I was just curious to know why structs, strings etc are immutable? What is the reason for making them immutable and rest of the objects as mutable. What are the things that are considered to make an object immutable?
Is there any difference on the way how memory is allocated and deallocated for mutable and immutable objects?
If this subject interests you, I have a number of articles about immutable programming at http://blogs.msdn.com/b/ericlippert/archive/tags/immutability/
I was just curious to know why structs, strings etc are immutable?
Structs and classes are not immutable by default, though it is a best practice to make structs immutable. I like immutable classes too.
Strings are immutable.
What is the reason for making them immutable and rest of the objects as mutable.
Reasons to make all types immutable:
It is easier to reason about objects that do not change. If I have a queue with three items in it, I know it is not empty now, it was not empty five minutes ago, it will not be empty in the future. It's immutable! Once I know a fact about it, I can use that fact forever. Facts about immutable objects do not go stale.
A special case of the first point: immutable objects are much easier to make threadsafe. Most thread safety problems are due to writes on one thread and reads on another; immutable objects don't have writes.
Immutable objects can be taken apart and re-used. For example, if you have an immutable binary tree then you can use its left and right subtrees as subtrees of a different tree without worrying about it. In a mutable structure you typically end up making copies of data to re-use it because you don't want changes to one logical object affecting another. This can save lots of time and memory.
Reasons to make structs immutable
There are lots of reasons to make structs immutable. Here's just one.
Structs are copied by value, not by reference. It is easy to accidentally treat a struct as being copied by reference. For example:
void M()
{
S s = whatever;
... lots of code ...
s.Mutate();
... lots more code ...
Console.WriteLine(s.Foo);
...
}
Now you want to refactor some of that code into a helper method:
void Helper(S s)
{
... lots of code ...
s.Mutate();
... lots more code ...
}
WRONG! That should be (ref S s) -- if you don't do that then the mutation will happen on a copy of s. If you don't allow mutations in the first place then all these sorts of problems go away.
Reasons to make strings immutable
Remember my first point about facts about immutable structures staying facts?
Suppose string were mutable:
public static File OpenFile(string filename)
{
if (!HasPermission(filename)) throw new SecurityException();
return InternalOpenFile(filename);
}
What if the hostile caller mutates filename after the security check and before the file is opened? The code just opened a file that they might not have permission to!
Again, mutable data is hard to reason about. You want the fact "this caller is authorized to see the file described by this string" to be true forever, not until a mutation happens. With mutable strings, to write secure code we'd constantly have to be making copies of data that we know do not change.
What are the things that are considered to make an object immutable?
Does the type logically represent something that is an "eternal" value? The number 12 is the number 12; it doesn't change. Integers should be immutable. The point (10, 30) is the point (10, 30); it doesn't change. Points should be immutable. The string "abc" is the string "abc"; it doesn't change. Strings should be immutable. The list (10, 20, 30) doesn't change. And so on.
Sometimes the type represents things that do change. Mary Smith's last name is Smith, but tomorrow she might be Mary Jones. Or Miss Smith today might be Doctor Smith tomorrow. The alien has fifty health points now but has ten after being hit by the laser beam. Some things are best represented as mutations.
Is there any difference on the way how memory is allocated and deallocated for mutable and immutable objects?
Not as such. As I mentioned before though, one of the nice things about immutable values is that something you can re-use parts of them without making copies. So in that sense, memory allocation can be very different.
Change the value of a property of a struct in C# [duplicate]
问题:
This question already has an answer here:
- Why are C# structs immutable? 5 answers
I was reading a book and found out that structs are actually immutable objects. But they have getters and setters. I was wondering if a property of structs can be changed after it has been created.
public struct Test
{
public string str {get; set; }
public int int1 {get; set; }
}
Can the values of 'str' and 'int1' be changed once they have been assigned a value?
解答:
struct
s are not automatically immutable, but because of certain issues it is strongly recommended to make them immutable yourself. You may be thinking of a similar problem where you can't change the properties of a struct if the struct is itself being accessed as a property (one of the reasons why it is recommended to make them immutable.) Using your Test
example:
public struct Test {
public string str { get; set; }
public int int1 { get; set; }
}
// This works:
Test value = new Test();
value.str = "asdf";
value.int1 = 5;
// But this does NOT work.
Test TestProperty { get; set; }
TestProperty.str = "asdf";
TestProperty.int1 = 5;
The reason the second part doesn't work is that you are only getting a value copy by saying TestProperty
, and then you set the value of the copy's properties, rather than the one in your object.
To make your struct immutable you would do something like this:
public struct Test {
readonly string mStr;
readonly int mInt1;
public string str { get { return mStr; } }
public int int1 { get { return mInt1; } }
public Test(string pStr, int pInt1) {
mStr = pStr;
mInt1 = pInt1;
}
}
You can create instances of Test
, you can read their properties, but you can't change their properties, except by making a new instance.
Accessing and changing structs as property vs as field
问题
Ok, I'll start my question saying that I understand the evil behind mutable structs, but I'm working with SFML.net and using a lot of Vector2f and such structs.
What I don't get it is why I can have, and change the values of, a field in a class and can't do the same with a property, in the very same class.
Take a look at this code:
using System;
namespace Test
{
public struct TestStruct
{
public string Value;
}
class Program
{
TestStruct structA;
TestStruct structB { get; set; }
static void Main(string[] args)
{
Program program = new Program();
// This Works
program.structA.Value = "Test A";
// This fails with the following error:
// Cannot modify the return value of 'Test.Program.structB'
// because it is not a variable
//program.structB.Value = "Test B";
TestStruct copy = program.structB;
copy.Value = "Test B";
Console.WriteLine(program.structA.Value); // "Test A"
Console.WriteLine(program.structB.Value); // Empty, as expected
}
}
}
note: I'll build my own classes to cover the same functionality and keep with my mutability, but I can't see a technical reason why I can do one and can't do other.
解答:
When you access a field, you are accessing the actual struct. When you access it through property, you call a method that returns whatever is stored in the property. In the case of a struct, which is a value type, you will get back a copy of the struct. Apparently that copy is not a variable and cannot be changed.
Section "1.7 Structs" of the C# language specification 5.0 says:
With classes, it is possible for two variables to reference the same object and thus possible for operations on one variable to affect the object referenced by the other variable. With structs, the variables each have their own copy of the data, and it is not possible for operations on one to affect the other.
That explains that you will receive a copy of the struct and not be able to modify the original struct. However, it doesn't describe why it isn't allowed.
Section "11.3.3" of the specifcation:
When a property or indexer of a struct is the target of an assignment, the instance expression associated with the property or indexer access must be classified as a variable. If the instance expression is classified as a value, a compile-time error occurs. This is described in further detail in §7.17.1.
So the returned "thing" from the get accessor is a value and not a variable. That explains the wording in the error message.
The specification also contains an example in section 7.17.1 that is nearly identical to your code:
Given the declarations:
struct Point
{
int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int X {
get { return x; }
set { x = value; }
}
public int Y {
get { return y; }
set { y = value; }
}
}
struct Rectangle
{
Point a, b;
public Rectangle(Point a, Point b) {
this.a = a;
this.b = b;
}
public Point A {
get { return a; }
set { a = value; }
}
public Point B {
get { return b; }
set { b = value; }
}
}
in the example
Point p = new Point();
p.X = 100;
p.Y = 100;
Rectangle r = new Rectangle();
r.A = new Point(10, 10);
r.B = p;
the assignments to p.X, p.Y, r.A, and r.B are permitted because p and r are variables. However, in the example
Rectangle r = new Rectangle();
r.A.X = 10;
r.A.Y = 10;
r.B.X = 100;
r.B.Y = 100;
the assignments are all invalid, since r.A and r.B are not variables.
Why are C# structs immutable?的更多相关文章
- [易学易懂系列|rustlang语言|零基础|快速入门|(11)|Structs结构体]
[易学易懂系列|rustlang语言|零基础|快速入门|(11)] 有意思的基础知识 Structs 我们今天来看看数据结构:structs. 简单来说,structs,就是用来封装相关数据的一种数据 ...
- Immutable(不可变)集合
不可变集合,顾名思义就是说集合是不可被修改的.集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变. 为什么要用immutable对象?immutable对象有以下的优点: 对不可靠的客户代 ...
- [LeetCode] Range Sum Query 2D - Immutable 二维区域和检索 - 不可变
Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper lef ...
- [LeetCode] Range Sum Query - Immutable 区域和检索 - 不可变
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive ...
- 扼杀 304,Cache-Control: immutable
随着近些年社交网站的流行,越来越多的人学会了“刷”网页 ── 刷微博,刷朋友圈,刷新闻,刷秒杀页.这里的“刷”,就是刷新的意思,在浏览器里,你可以通过点击刷新按钮,或者用快捷键,或者移动端的下拉操作来 ...
- Structs框架
一.准备工作及实例 1.解压struts-2.1.6-all.zip(structs网上下载) apps目录:struts2自带的例子程序 docs目录:官方文档. lib 目录:存放所有jar文件. ...
- Immutable api example
var temp=[{name:"kitty",age:31},{name:"ff",age:22},{name:"kitty",age:4 ...
- Immutable笔记
Immutable笔记 转换成js数据 获取或则改变嵌套式imutable数据类型
- 第一个structs+spring+hibernate的web程序
1. 数据库: Column Type Comment id int(11) Auto Increment name varchar(50) NULL url varchar(255) NUL ...
随机推荐
- Flask框架学习篇(一)
安装好Python,pip install flask安装好flask后,开始编写第一个flask程序 #包含动态路由的flask程序from flask import Flask app= Flas ...
- 第五篇.python进阶
目录 第五篇.python进阶 1. 异常处理 2. 数字类型内置方法 2.定义: 3.常用操作+内置方法: 4.存一个值or多个值: 5.有序or无序: 6.可变和不可变 1.用途: 2.定义: 3 ...
- 深入学习Mybatis框架(一)- 入门
1.什么是Mybatis? Mybatis是一个优秀持久层框架,提供了对数据库的一系列操作(增删改查).Mybatis可以避免重复的写JDBC代码,让我们以较少的代码实现对数据库的操作,从而提高开发效 ...
- mysql调优——数据包大小限制max_allowed_packet
mysql根据配置文件会限制server接受的数据包大小. 有时候大的插入和更新会受max_allowed_packet 参数限制,导致写入或者更新失败. 查看目前配置 show VARIABLES ...
- LeetCode NO477.汉明距离总和
两个整数的 汉明距离 指的是这两个数字的二进制数对应位不同的数量. 计算一个数组中,任意两个数之间汉明距离的总和. 示例: 输入: 4, 14, 2 输出: 6 解释: 在二进制表示中,4表示为010 ...
- linux工具之lsof
1.lsof ( list open files) lsof(list open files) 是一个列出当前系统打开文件的工具.在linux环境下,任何事物都以文件的形式存在,通 ...
- IIS 调试配置
- 布隆算法(BloomFilter)
BloomFilter算法,是一种大数据排重算法.在一个数据量很大的集合里,能准确断定一个对象不在集合里:判断一个对象有可能在集合里,而且占用的空间不大.它不适合那种要求准确率很高的情况, ...
- kubernetes(K8S)快速安装与配置集群搭建图文教程
kubernetes(K8S)快速安装与配置集群搭建图文教程 作者: admin 分类: K8S 发布时间: 2018-09-16 12:20 Kubernetes是什么? 首先,它是一个全新的基于容 ...
- uoj30【CF Round #278】Tourists(圆方树+树链剖分+可删除堆)
- 学习了一波圆方树 学习了一波点分治 学习了一波可删除堆(巧用 ? STL) 传送门: Icefox_zhx 注意看代码看怎么构建圆方树的. tips:tips:tips:圆方树内存记得开两倍 CO ...