有关.net编程的几点困惑

nicochang 2003-09-22 01:43:17
我原先是写c++的,现在正在看.net,我有几个疑问始终弄不明白,希望高手能给解答
1.有关函数以对象为参数,传递变量
using System;

namespace TestRef
{
/// <summary>
/// Class1 的摘要说明。
/// </summary>
public class c1
{
public int a;
public c1()
{
a = 10;
}
public c1(c1 c)
{
a = c.a;
}
}
public class TestRef
{

public static void f(c1 c)
{
c.a = 20;
}
public static void Main(String[] args)
{

c1 c;
c = new c1();
Console.WriteLine("{0}",c.a);
f(c);
Console.WriteLine("{0}",c.a);
}
}
}
输出的结果是
10
20
原因我也知道,是由于类是引用型的类型。在c++中,我可以在c1类中,写一个拷贝构造函数,在函数传递变量和返回变量的时候,提供一个副本,那样的话,输出结果就可以是10,10了,那么在.net里有没有类似的机制。Clone()方法需要手动的去调用,那么是不是如果需要,要在函数的入口出写上Clone()呢,还是有其他的方法,还是我用c++的思考方法,去考虑.net了
我知道在String中实现了,但是,String返回的新的字符串,那究竟是怎么做的
第二个问题,在msdn中讲.net不支持=的重载,但是我看到很多书上都讲string对=进行了重载,那么到底能不能重载
...全文
50 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
jeng 2003-09-22
  • 打赏
  • 举报
回复
习惯?!
nicochang 2003-09-22
  • 打赏
  • 举报
回复
如果是这样的话,在平时设计的时候,还是要注意的。也许是我写c++的程序写多了:)
jjcccc 2003-09-22
  • 打赏
  • 举报
回复
你说的很对,可能是在编译阶段就对string进行了特别处理!?
nicochang 2003-09-22
  • 打赏
  • 举报
回复
那么,现在,可以肯定的一点是,第一个问题实际上并不存在,string用的还是引用传值,关键是在赋值操作上,但是,汇编代码看,并不像对=进行了重载
jjcccc 2003-09-22
  • 打赏
  • 举报
回复
比较一下楼主的void f(c1 c)方法的汇编代码:

.method /*06000003*/ public hidebysig static
void f(class TestRef.c1/* 02000002 */ c) cil managed
{
// Code size 9 (0x9)
.maxstack 2
.language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'f:\mystudio\c#\consoleapplication6\class1.cs'

//000025: c.a = 20;
IL_0000: ldarg.0
IL_0001: ldc.i4.s 20

//下面这句就是不同的地方,对字符串用的是 starg.s s//将堆栈中的值复制到s中
IL_0003: stfld int32 TestRef.c1/* 02000002 */::a /* 04000001 */
//000026: }
IL_0008: ret
} // end of method TestRef::f
jjcccc 2003-09-22
  • 打赏
  • 举报
回复
这是我上面例子的反汇编后的代码,正在琢磨...,好像有点感觉:
method /*06000001*/ private hidebysig static
void Main(string[] args) cil managed
{
.entrypoint
.custom /*0C000001:0A00000E*/ instance void [mscorlib/* 23000001 */]System.STAThreadAttribute/* 0100000F */::.ctor() /* 0A00000E */ = ( 01 00 00 00 )
// Code size 31 (0x1f)
.maxstack 1
.locals /*11000001*/ init ([0] string s)
.language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'f:\mystudio\c#\consoleapplication5\class1.cs'
//000016: string s="1234";
IL_0000: ldstr "1234" /* 70000001 */
IL_0005: stloc.0
//000017: Console.WriteLine(s);
IL_0006: ldloc.0
IL_0007: call void [mscorlib/* 23000001 */]System.Console/* 01000010 */::WriteLine(string) /* 0A00000F */
//000018:
//000019: Change(s);
IL_000c: ldloc.0
IL_000d: call void ConsoleApplication5.Class1/* 02000002 */::Change(string) /* 06000002 */
//000020:
//000021: Console.WriteLine(s);
IL_0012: ldloc.0
IL_0013: call void [mscorlib/* 23000001 */]System.Console/* 01000010 */::WriteLine(string) /* 0A00000F */
//000022:
//000023: Console.ReadLine();
IL_0018: call string [mscorlib/* 23000001 */]System.Console/* 01000010 */::ReadLine() /* 0A000010 */
IL_001d: pop
//000024:
//000025:
//000026: }
IL_001e: ret
} // end of method Class1::Main

.method /*06000002*/ public hidebysig static
void Change(string s) cil managed
{
// Code size 14 (0xe)
.maxstack 1
.language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'f:\mystudio\c#\consoleapplication5\class1.cs'
//000030: s="changed!";
IL_0000: ldstr "changed!" /* 7000000B */
IL_0005: starg.s s
//000031: Console.WriteLine(s);
IL_0007: ldarg.0
IL_0008: call void [mscorlib/* 23000001 */]System.Console/* 01000010 */::WriteLine(string) /* 0A00000F */
//000032: }
IL_000d: ret
} // end of method Class1::Change
nicochang 2003-09-22
  • 打赏
  • 举报
回复
我现在还搞不清string的这种特性是在函数传值是就表现出来了,还是像我上面说的,只是在赋值时才有
nicochang 2003-09-22
  • 打赏
  • 举报
回复
to jjcccc() :
你的说法对我有了些启发,如果按你的说法,那么实际上在Change(string s)的时候,string和其他的没有区别,而这真正关键的是s="changed!";这句,这句让函数里的s和外面的s有了区分,成为两个变量,如果是这样的话,那么我的两个问题,可能可以归结为一个,就是怎样重载的=
不知道我的想法对不对,也许有问题
jjcccc 2003-09-22
  • 打赏
  • 举报
回复
string确实比较特殊,如

class Class1
{
[STAThread]
static void Main(string[] args)
{
string s="1234";
Console.WriteLine(s);//输入1234

Change(s);

Console.WriteLine(s);//输入1234

Console.ReadLine();
}

public static void Change(string s)
{
s="changed!";
Console.WriteLine(s);//changed!
}
}

因为在Change方法中;执行s="changed!";时实质是.net CLR构造一个新的字符串"changed!",并将s指向这个新生成的字符串的新的地址(在托管堆中)。这大概和CLR的特别处理有关吧!所以到达了向传值一样的效果。问题是内部具体是怎样处理的呢,我们自己写的类可以做到这样吗?
这个问题确实值得研究。
nicochang 2003-09-22
  • 打赏
  • 举报
回复
我指的机制是相string那样,外面并没有做任何操作,完全是由类自己完成的
nicochang 2003-09-22
  • 打赏
  • 举报
回复
解决的方法,肯定很多,我在函数的入口处,加上一个Clone(),应该也可以,但是我想知道的就是,实现的机制,还有,就是这样设计合不合理,在c++里加一个拷贝构造函数,就可以了,这也是标准的解决办法,但是,在.net里呢,还是根本不需要解决,因为就不要让它出现

xunx 2003-09-22
  • 打赏
  • 举报
回复
C#都是参数引用
nicochang 2003-09-22
  • 打赏
  • 举报
回复
我在怀疑,是不是,我的设计想法有问题,.net里就不会出现这种设计
hydnoahark 2003-09-22
  • 打赏
  • 举报
回复
你可以考虑为class c1增加一个公共属性:
public c1 MemObject
{
get
{
return new c1(this);
}
set
{
this.a = value.a;
}
}

客户端代码:
c1 c;
c = new c1();
Console.WriteLine("{0}",c.a);
c1 memObject = c.MemObject; <<===
f(c);
Console.WriteLine("{0}",c.a);
c.MemObject = memObject; <<===
Console.WriteLine("{0}",c.a);
jjcccc 2003-09-22
  • 打赏
  • 举报
回复
也许是这样来,能简单达到你的目的,但解决不了你的迷惑(你的1,2说的都对,我也在迷惑呢…)
public static void Main(String[] args)
{

c1 c;
c = new c1();
Console.WriteLine("{0}",c.a);
f(new c1(c));
Console.WriteLine("{0}",c.a);
}
nicochang 2003-09-22
  • 打赏
  • 举报
回复
to xz_king(西杀魄工人)
我没看明白。我觉得我现在就是引用调用
我想要的是一种类似于传值的调用效果。还有一点更重要的就是,是不是我想要的这种写法在.net里就是一种错误的想法。而string 不过就是一个特例
xz_king 2003-09-22
  • 打赏
  • 举报
回复
static void Trans(ref object obj){};

调用: xxx.Trans(ref obj);
nicochang 2003-09-22
  • 打赏
  • 举报
回复
比如我要实现一些基础的类型,描述一个人,某一种东西,我可能会把它的对象在函数里传来传去的,那应该怎么写
nicochang 2003-09-22
  • 打赏
  • 举报
回复
那应该怎么办,难道,不会出现这样的要求吗
i_am_a_frog 2003-09-22
  • 打赏
  • 举报
回复
你用c++的思考方法,去考虑.net了!

110,537

社区成员

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

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

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