在C#中如何保证传入参数不会被改变? 一般情况下都不会改变,除非你用 ref 和 out 关键字 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 那要看你的参数是什么类型的,一般数据类型的参数只要不加out ,ref申明是不会被改变的 還可用 const加在類型前,這樣如要改變,則會出錯 好像加const是一种方法!将其做成属性吧!然后将属性作参数! 把参数定义为常量嘛!比如:const int a = 10;这样就不会被修改了呀! 我晕难道你们传递的都是value type?ref type传递时是不能保证其内部状态不发生改变的。C++这种基于value的语言可以使用const,难道在C#里也能在传入的ref type前加上const? 你如果要求ref type的内部不发生改变的话,最好clone一下。一般的类都已经给你写好这个clone函数了,如果是你的类,重写一下这个函数,然后clone一个出来。 [attributes] [modifiers] const type declarators;此处: attributes(可选) 可选的声明信息。有关属性和属性类的更多信息,请参阅 C# 属性。 modifiers(可选) 包括 new 修饰符和四个访问修饰符之一的可选修饰符。 type 这些类型之一:byte、char、short、int、long、float、double、decimal、bool、string、枚举类型或引用类型。没有说引用类型不可以呀!!!!!!!!!! sumtec(Psydian)good method, 就是空间有点浪费,如果没有好方法,分就是你的:) snewxf(心疤) 看清楚我问的再发话,简直文不对题。 我觉得也是clone比较好,好像没有什么更好的办法。 支持 不用 out / ref 方法参数而clone 不是解。 传入的参数默认只是传入其一个copy而已,怎么会改变?如果你使用out,ref关键字才会被改变--传入的是地址。 要看你是引用传 还是值传递 若是引用传 是不会改变的若是值类型的话,在传参数的时候,就要加个ref 表明是引用传就可以了 Struct的都是传值,在C#中Struct是作为原始类型来对待的,存在于栈中,Class的只能参照,存在于堆,由GC管理,定义为Const是可以保证不变,但是作为定义方式,不能保证在调用时不抛出错误。Clone相当于原始型的复制,需要结构支持IClone接口,或由自己来实现IClone接口。至于为什么要用Clone一方面是为了解决语法上的岐义,另一方面跟装箱和消箱的实现有关联。举个例子清楚些://c#string s1 = "aaaaa";string s2 = new string(s1); //编译器通知错误,并且建议使用类似Clone的方法。[btw:在JAVA中是允许的]想想以下几种情况互转吧:----------------------结构到结构结构到对像(注意一下是己实例化的和对像工厂的情况)对像到结构(注意一下是己实例化的)对像到对像---------------------- 大哥们你们到底懂不懂我问的是什么?我简直要faint到死。 哎呀呀呀,原来还有这么多人没有搞清楚概念啊??class 相当于 ref struct如果参数是一个class,或者说某个变量是一个class,那么实际上这个变量/参数只是一个指针,这个指针指向一个struct。如果你不写ref,或者你的变量定义为const/readonly是没有用的,因为这只是保护了这个指针不被改变,或者作为参数的时候传送的是这个指针的一个拷贝。所以在函数的内部你是不能够改变这个变量,eg:readonly class1 c = new class1();c = new class1(); // 这是不行的,这个指针不能够变c.Text = "asdkfs"; // 这样倒是可以的,只要这个Text属性有set, // 或者这个Text字段没有被readonly修饰class1 d = new class1();foo(d);void foo(class1 xxx){ xxx = new class1(); // 这样是不会修改到外面的d, // 因为这个xxx只是压到堆栈的一个指针的拷贝。}foo2(d);void foo2(class1 xxx){ xxx.Text = "dsafksl" // 但是你却没有办法阻止这个d.Text的改变,因为虽然堆栈 // 的是指向某个struct的一个指针的拷贝,但是这个拷贝和 // d 一样,指向的是都是同一个struct或者说对象。对xxx.Text // 的修改就是对d.Text的修改。}明白了没有? 楼主,如果你不希望别人改变你的这个对象,那么你就应该尽量不暴露这个对象才对。或者对那些不应该被修改的属性仅提供get,不提供set。对自己的类应该公开另外一套东西(用internal修饰,但这样其实如果不是情非得已最好不要用)。当然,这个的前提是这是你自己写的类。还有一个办法,写一个private/internal的interface,那么只有自己的方法能够通过这个内部的interface访问到。 呵, 无语千万别以为别人和自己一样无知。好歹我学C++也有几个年头,这点基本概念,我比你清楚。属于同一类作用域中的方法,是可以改变这个类对象的内部状态的。class Base{ public void Fun(Base b)}; sorry 发错了class Base{ private int x; public void Fun(Base b) { // b.x = 323; }}我问的是这里的Base.Fun如何保证不会改变b的内容。因为它可能只需要读取其成员。 如果只提供Get,那么在其他情况下需要修改呢?比如不是这个方法。用Clone是可以起效果的,但是动静大了点。 const是将参数转换成常量了!使用不方便,不推荐! 我那个帖子是说给那些给你建议用const或者不用ref的人的,不是写给你的,无需激动。如果是你自己的类里面的东西就应该保证不会出错,没有别的办法。像你所说的情况时基本上是没有办法通过限定避免的,只有看你自己的代码质量了。你没有说清楚当然不能怪我说得不对啦。当然,如果你能够确定只有某些属性可能会被修改,那么还是有别的办法的,但是就比较复杂了:private bool busy = false;public int MyValue{ get { return ...; } set { if (busy) return; ... = value; }}void foo1() // 这个方法可以命名为SafeFoo2{ myobj.busy = true; // 这里的myobj可以是this foo2(myobj); myobj.busy = false;}void foo2(myclass obj){ obj.MyValue = ...; // 通过foo1可以避免被修改。或者进入前修改busy。}当然,这只是一个快速开发方法,对于一个属性还能够胜任,多了就会有各种麻烦。当然,还有好多其他办法。 还有就比如说,当你需要禁止某一个函数对某些东西的修改的话,而这样的禁止并不多见,那么你可以在进入这个函数之前进行现场保护,比如说用另一些变量把这些属性都保护起来,然后再进入,退出的时候恢复。其实就是局部Clone。恕我直言,你的问题我是觉得很奇怪,当然,我的意思不是指没有可能出现这样的需求,但是一般来说能够通过一些变换来处理,而不需要“禁止修改”。因为你的这个情况是出现在你自己的类里面的:class Base{ private int x; public void Fun(Base b) { b.x = 323; // 你的这句话的意思不是期望对这个变量进行修改吗? // 如果你不希望对b.x进行修改,那么就是跟你的原意相矛盾的。 // 如果在某种情况下你不希望对他修改,那么就应该在这句话之前 // 加上一个判断。如果你这个函数有很多地方对他禁止修改,那么 // 你就应该考虑一下,是不是在某种情况下就应该推出这个函数。 // 如果还有其他代码在这种情况下是必需的,那么我就觉得那是两个 // 不同的功能,应该进行功能分离,不应该写到一个函数里面。 }}我不清楚你的目的是什么,你把完整的代码贴出来或许能够帮你。 这里写出b.x = 323;只是说明在这里可能改变b的成员,并不是说一定会这样做。有时候我们在自己改变了对象内部成员的时候也不会知道,这种情况比较容易引起逻辑错误。我指的就是这种情况。在C++中,由于对象是基于值的,struct 与class在本质上并没有区别,所以可以在参数列里加入const进行声明。这样就能保证参数的内部状态不会发生变化。因为可以传递const ref,所以也没有多的空间开销。但是在C#中并不允许在ref上使用const, 因为C#中的const确实是真正的const,没有空间。readonly也只能放在类中的成员上,不能放在传递变量上。你在最后提到的是assert功能吗?那样也可以有效,就是麻烦了点。写这个帖子我只是想看看C#中是否有比较方便的方法保证其内部状态不发生改变。 不同意sumtec(Psydian) 的说法:---------------class 相当于 ref struct如果参数是一个class,或者说某个变量是一个class,那么实际上这个变量/参数只是一个指针,这个指针指向一个struct。---------------在C++中还说的过去,那是先定义了对象,然后那么马上分配其内存,之后调用其构造函数,这个内存可能在堆中,也可能在栈内,也可能在全局数据区内。---但C#中却截然不同,定义一对象,只是先为其分配一个空间,而真正的对象空间还没有分配,在使用前当给对象分配空间,这个对象空间是分配在堆内的,---Struct是标准的分配在栈中,Class是指向的堆不是参照到栈中。 请教: CMD文件里有个外部命令,WINFORM里执行CMD文件出错 c#从SQL中读取数据到DataTable中日文数据乱码的问题 关于序列化与反序列化 VB代码转换成C#代码? C#获取网页标题.速度.下班结帖.. 大家帮忙!!! winform中datagridview的rowleave事件 WinForm问题...Form2怎么获取Form1的按钮事件! 请高手指点DataGrid编辑的一个问题 大家帮我看看,不是很复杂的问题 請大家幫我解決一下! 怎样检测一台计算机里是否已经安装了.net framework
比如:
const int a = 10;
这样就不会被修改了呀!
难道你们传递的都是value type?
ref type传递时是不能保证其内部状态不发生改变的。
C++这种基于value的语言可以使用const,难道在C#里也能在传入的ref type前加上const?
此处: attributes(可选)
可选的声明信息。有关属性和属性类的更多信息,请参阅 C# 属性。
modifiers(可选)
包括 new 修饰符和四个访问修饰符之一的可选修饰符。
type
这些类型之一:byte、char、short、int、long、float、double、decimal、bool、string、枚举类型或引用类型。
没有说引用类型不可以呀!!!!!!!!!!
good method, 就是空间有点浪费,如果没有好方法,分就是你的:)
看清楚我问的再发话,简直文不对题。
而clone 不是解。
如果你使用out,ref关键字才会被改变--传入的是地址。
若是引用传 是不会改变的
若是值类型的话,在传参数的时候,就要加个ref 表明是引用传就可以了
在C#中Struct是作为原始类型来对待的,
存在于栈中,
Class的只能参照,
存在于堆,由GC管理,
定义为Const是可以保证不变,
但是作为定义方式,
不能保证在调用时不抛出错误。
Clone相当于原始型的复制,
需要结构支持IClone接口,
或由自己来实现IClone接口。至于为什么要用Clone一方面是为了解决语法上的岐义,
另一方面跟装箱和消箱的实现有关联。
举个例子清楚些:
//c#
string s1 = "aaaaa";
string s2 = new string(s1);
//编译器通知错误,并且建议使用类似Clone的方法。
[btw:在JAVA中是允许的]想想以下几种情况互转吧:
----------------------
结构到结构
结构到对像(注意一下是己实例化的和对像工厂的情况)
对像到结构(注意一下是己实例化的)
对像到对像
----------------------
我简直要faint到死。
如果参数是一个class,或者说某个变量是一个class,那么实际上这个变量/参数只是一个指针,这个指针指向一个struct。如果你不写ref,或者你的变量定义为const/readonly是没有用的,因为这只是保护了这个指针不被改变,或者作为参数的时候传送的是这个指针的一个拷贝。所以在函数的内部你是不能够改变这个变量,eg:readonly class1 c = new class1();c = new class1(); // 这是不行的,这个指针不能够变
c.Text = "asdkfs"; // 这样倒是可以的,只要这个Text属性有set,
// 或者这个Text字段没有被readonly修饰class1 d = new class1();foo(d);void foo(class1 xxx)
{
xxx = new class1(); // 这样是不会修改到外面的d,
// 因为这个xxx只是压到堆栈的一个指针的拷贝。
}foo2(d);void foo2(class1 xxx)
{
xxx.Text = "dsafksl" // 但是你却没有办法阻止这个d.Text的改变,因为虽然堆栈
// 的是指向某个struct的一个指针的拷贝,但是这个拷贝和
// d 一样,指向的是都是同一个struct或者说对象。对xxx.Text
// 的修改就是对d.Text的修改。
}明白了没有?
当然,这个的前提是这是你自己写的类。还有一个办法,写一个private/internal的interface,那么只有自己的方法能够通过这个内部的interface访问到。
千万别以为别人和自己一样无知。好歹我学C++也有几个年头,这点基本概念,我比你清楚。属于同一类作用域中的方法,是可以改变这个类对象的内部状态的。class Base
{
public void Fun(Base b)};
{
private int x;
public void Fun(Base b)
{
// b.x = 323;
}
}我问的是这里的Base.Fun如何保证不会改变b的内容。因为它可能只需要读取其成员。
用Clone是可以起效果的,但是动静大了点。
像你所说的情况时基本上是没有办法通过限定避免的,只有看你自己的代码质量了。
你没有说清楚当然不能怪我说得不对啦。当然,如果你能够确定只有某些属性可能会被修改,那么还是有别的办法的,但是就比较复杂了:private bool busy = false;public int MyValue
{
get
{
return ...;
}
set
{
if (busy)
return;
... = value;
}
}void foo1() // 这个方法可以命名为SafeFoo2
{
myobj.busy = true; // 这里的myobj可以是this
foo2(myobj);
myobj.busy = false;
}void foo2(myclass obj)
{
obj.MyValue = ...; // 通过foo1可以避免被修改。或者进入前修改busy。
}当然,这只是一个快速开发方法,对于一个属性还能够胜任,多了就会有各种麻烦。当然,还有好多其他办法。
{
private int x;
public void Fun(Base b)
{
b.x = 323; // 你的这句话的意思不是期望对这个变量进行修改吗?
// 如果你不希望对b.x进行修改,那么就是跟你的原意相矛盾的。
// 如果在某种情况下你不希望对他修改,那么就应该在这句话之前
// 加上一个判断。如果你这个函数有很多地方对他禁止修改,那么
// 你就应该考虑一下,是不是在某种情况下就应该推出这个函数。
// 如果还有其他代码在这种情况下是必需的,那么我就觉得那是两个
// 不同的功能,应该进行功能分离,不应该写到一个函数里面。
}
}
我不清楚你的目的是什么,你把完整的代码贴出来或许能够帮你。
在C++中,由于对象是基于值的,struct 与class在本质上并没有区别,所以可以在参数列里加入const进行声明。这样就能保证参数的内部状态不会发生变化。因为可以传递const ref,所以也没有多的空间开销。
但是在C#中并不允许在ref上使用const, 因为C#中的const确实是真正的const,没有空间。readonly也只能放在类中的成员上,不能放在传递变量上。你在最后提到的是assert功能吗?那样也可以有效,就是麻烦了点。
写这个帖子我只是想看看C#中是否有比较方便的方法保证其内部状态不发生改变。
---------------
class 相当于 ref struct
如果参数是一个class,或者说某个变量是一个class,
那么实际上这个变量/参数只是一个指针,这个指针指向一个struct。
---------------
在C++中还说的过去,
那是先定义了对象,
然后那么马上分配其内存,
之后调用其构造函数,
这个内存可能在堆中,
也可能在栈内,
也可能在全局数据区内。
---
但C#中却截然不同,定义一对象,
只是先为其分配一个空间,
而真正的对象空间还没有分配,
在使用前当给对象分配空间,
这个对象空间是分配在堆内的,
---
Struct是标准的分配在栈中,
Class是指向的堆不是参照到栈中。