C# 函数只读参数

Yanger_xy 2011-06-16 08:57:43
请问:C#中如何定义一个函数,另其参数在函数体内是只读的.void test(ClassA p),其中参数是一个类(引用类型)
谢谢!
...全文
686 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
twtyypmb123 2014-01-06
  • 打赏
  • 举报
回复
嗯,我在C# primer plus里也看到了一句话,“C++中的指针等价于C#中的引用”,在结合版主的话,可以推出,C#和C语言一样,参数传递本质上是值传递,没有“引用传递”,所谓的“引用”,只是把外部的引用“赋值”给了内部的参量而已,然后经过寻址修改就可以改变外部引用所引用的对象
#blackheart 2014-01-05
  • 打赏
  • 举报
回复
引用 27 楼 x3230835 的回复:
[quote=引用 26 楼 x3230835 的回复:] [quote=引用 24 楼 NianHui 的回复:] [Quote=引用 22 楼 cpp_yangzuoshi 的回复:] …… [/Quote] 首先你要分清楚按引用传递引用类型的参数的不同,这点在,.NET框架程序设计(修订版),第9章第5小节有详细的解释。 其次推荐你看篇博客
C#的引用给我的感觉很像指针,依我看来,值类型在创建对象的时候得到的是对象本身,而引用类型在创建时得到的是它的地址(当然很有可能这个地址不是物理地址,但也是通过它计算得到的),所以在复制参数的时候,值类型的修改不会影响到外部的本身,而引用类型的参数在复制引用后能改变对象的值是因为寻址的原因,相当于两个指针指向了同一个地址,不知道正确否[/quote] 还请版主看一下我这理解的有问题没? C#语言版
class Entry
{
	public static void Main()
	{
		int a = 1;
		Set( ref a );
	}
	
	public static void Set( ref int b )
	{
		b = 2;
	}
}
C语言
void Set( int *b )
{
	*b = 2;
}

int main( void )
{
	int a = 1;
	Set( &a ); //&相当于C#中的ref
}
[/quote] 对的对的,完全正确。
twtyypmb123 2014-01-03
  • 打赏
  • 举报
回复
引用 26 楼 x3230835 的回复:
[quote=引用 24 楼 NianHui 的回复:] [Quote=引用 22 楼 cpp_yangzuoshi 的回复:] …… [/Quote] 首先你要分清楚按引用传递引用类型的参数的不同,这点在,.NET框架程序设计(修订版),第9章第5小节有详细的解释。 其次推荐你看篇博客
C#的引用给我的感觉很像指针,依我看来,值类型在创建对象的时候得到的是对象本身,而引用类型在创建时得到的是它的地址(当然很有可能这个地址不是物理地址,但也是通过它计算得到的),所以在复制参数的时候,值类型的修改不会影响到外部的本身,而引用类型的参数在复制引用后能改变对象的值是因为寻址的原因,相当于两个指针指向了同一个地址,不知道正确否[/quote] 还请版主看一下我这理解的有问题没? C#语言版
class Entry
{
	public static void Main()
	{
		int a = 1;
		Set( ref a );
	}
	
	public static void Set( ref int b )
	{
		b = 2;
	}
}
C语言
void Set( int *b )
{
	*b = 2;
}

int main( void )
{
	int a = 1;
	Set( &a ); //&相当于C#中的ref
}
twtyypmb123 2014-01-03
  • 打赏
  • 举报
回复
引用 24 楼 NianHui 的回复:
[Quote=引用 22 楼 cpp_yangzuoshi 的回复:] …… [/Quote] 首先你要分清楚按引用传递引用类型的参数的不同,这点在,.NET框架程序设计(修订版),第9章第5小节有详细的解释。 其次推荐你看篇博客
C#的引用给我的感觉很像指针,依我看来,值类型在创建对象的时候得到的是对象本身,而引用类型在创建时得到的是它的地址(当然很有可能这个地址不是物理地址,但也是通过它计算得到的),所以在复制参数的时候,值类型的修改不会影响到外部的本身,而引用类型的参数在复制引用后能改变对象的值是因为寻址的原因,相当于两个指针指向了同一个地址,不知道正确否
Yanger_xy 2011-06-18
  • 打赏
  • 举报
回复
在下基础不牢,还望诸位多多海涵,不吝赐教.


public class ClassA
{
public string _strValue = "defaultValue";
}

   
void RefTest(ClassA param)
{
param._strValue = "Changed";
}



ClassA srcClass = new ClassA();
print("Before function called : " + srcClass._strValue);
RefTest(srcClass);
print("After function called: " + srcClass._strValue);

这段代码输出结果为:
Before function called : defaultValue
After function called: Changed

将类作为参数,结果类的成员变量的值被改变了.这不是说明参数是按引用类型传递的吗?
还是说参数是按值传递的,但复制的是该变量的地址,而非复制的值.如果是这样的话,那么我的参数即使包含很大的数据量,不显示的用ref也不会影响性能?
兔子-顾问 2011-06-18
  • 打赏
  • 举报
回复
internal void Test()
{
ClassA srcClass = new ClassA();
Console.WriteLine("Before function called : " + srcClass._strValue);
RefTest(srcClass);
Console.WriteLine("After function called: " + srcClass._strValue);
}

void RefTest(ClassA param)
{
ClassA copy_one = (ClassA)param.Clone();
copy_one._strValue = "Changed";
}

public class ClassA:ICloneable
{
public string _strValue = "defaultValue";


#region ICloneable 成员

public object Clone()
{
return this.MemberwiseClone();
}

#endregion
}
#blackheart 2011-06-18
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 cpp_yangzuoshi 的回复:]
……
[/Quote]

首先你要分清楚按引用传递引用类型的参数的不同,这点在,.NET框架程序设计(修订版),第9章第5小节有详细的解释。

其次推荐你看篇博客
老毕 2011-06-18
  • 打赏
  • 举报
回复
原谅我在10楼未经实验的回复。我把C++里的(const 参数)混入C#里了。

在C#里,除了int、byte、char、bool等基本类型是值传递外,数组、string和其他的对象都是引用传递。而C#又不象C++提供了对函数参数的const修饰,所以当我们向函数传递某个对象时,是通过引用传递进去的,在函数内部对参数的修改,将直接引起该引用指向的对象改变。

C#里提供了ref和out修饰符,主要用于将按值传递的基础类型变为按引用传递。ref和out都建立一份引用,区别只是ref的值要求初始化。

当然,对于本身已经是按引用传递的对象,我们也可以进行ref或者out的修饰,个人理解是为了语义上更简洁和明了。

即,没有用ref或者out修饰的对象,在函数体内养成习惯,不要去进行更改。
老毕 2011-06-17
  • 打赏
  • 举报
回复
void test(const classA p)
#blackheart 2011-06-17
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 cgabriel 的回复:]

引用 6 楼 nianhui 的回复:

引用 2 楼 icedmilk 的回复:

没什么只读不只读的

C#传递的都是引用,你给形参p赋值又不会改变外面的什么东西

别在这误导人。默认传的都是“按值传递”


别在这误导别人,对于类来说都是按引用传递。。。
[/Quote]
请你再好好查查资料,默认都是按值传递,除非你用ref和out关键字标识才是按引用传递
flyerwing 2011-06-17
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 icedmilk 的回复:]
没什么只读不只读的

C#传递的都是引用,你给形参p赋值又不会改变外面的什么东西
[/Quote]
函数调用参数好象都是值传递.所以没必要吧.
CGabriel 2011-06-17
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 nianhui 的回复:]

引用 2 楼 icedmilk 的回复:

没什么只读不只读的

C#传递的都是引用,你给形参p赋值又不会改变外面的什么东西

别在这误导人。默认传的都是“按值传递”
[/Quote]

别在这误导别人,对于类来说都是按引用传递。。。
机器人 2011-06-17
  • 打赏
  • 举报
回复
那就告诉自己不要手欠去修改成员变量。。。

或者像caozhy说的,写个深拷贝的clone方法后再用。
threenewbee 2011-06-17
  • 打赏
  • 举报
回复
(1)你可以在方法体内再定义一个ClassA,复制过来。
(2)在方法体外,写一个断言,比较调用前后的GetHashCode()是否一致,如果不一致,说明被修改,果断中止程序丢出异常。
Yanger_xy 2011-06-17
  • 打赏
  • 举报
回复
ClassA 是别人写好的类,成员变量不能定义为readonly,也不能改成struct
#blackheart 2011-06-17
  • 打赏
  • 举报
回复
我就纳闷了,某些人分数也不低,居然连C#基础都还存在理解错误,【还默认是传引用,说出去不怕被人耻笑!】
#blackheart 2011-06-17
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 cpp_yangzuoshi 的回复:]

还是你好好查查资料吧,Class 是引用类型.作为函数的参数的时候也是按引用传递的.再加个ref就相当于C++中指针的指针.
。。。。。。
[/Quote]
不管你是引用类型还是值类型,C#默认都是按值传递。
例如

int i=10;
Conslole.WriteLine(i);//相当于把i存储的值复制一份给Conslole.WriteLine使用,内存中存在两个10

myType my=new myType();//假设myType是引用类型;
Conslole.WriteLine(my);//这是把my这个引用复制一份给Conslole.WriteLine使用,内存中有两个对myType实例的引用。
加上ref或者out则不会引起参数的复制,传递的是参数地址【值类型引用类型相同】
#blackheart 2011-06-17
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 fangxinggood 的回复:]

NianHui 真是屈死了。。。
[/Quote]
,无奈啊,唉
机器人 2011-06-17
  • 打赏
  • 举报
回复
NianHui 真是屈死了。。。
Yanger_xy 2011-06-17
  • 打赏
  • 举报
回复
还是你好好查查资料吧,Class 是引用类型.作为函数的参数的时候也是按引用传递的.再加个ref就相当于C++中指针的指针.
[Quote=引用 16 楼 nianhui 的回复:]

引用 14 楼 cgabriel 的回复:

引用 6 楼 nianhui 的回复:

引用 2 楼 icedmilk 的回复:

没什么只读不只读的

C#传递的都是引用,你给形参p赋值又不会改变外面的什么东西

别在这误导人。默认传的都是“按值传递”


别在这误导别人,对于类来说都是按引用传递。。。

请你再好好查查资料,默认都是按值传递,除非你用ref和ou……
[/Quote]
加载更多回复(9)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧