xlzhu's dotnet world

喜欢Google的软件、微软的技术......
随笔 - 58, 文章 - 2, 评论 - 562, 引用 - 7
数据加载中……

C#中的ref参数问题

先看一段代码:

ClassA

{

public string name;

}

Class B : ClassA {}

public static void Main()

{

ClassB b = new ClassB();

b.name = "I'm class b";

//如果用Test(ref b)的话,编译会提示无法转换ClassB到ClassA

Console.WriteLine(Test(ref (ClassA)b));

}

public static string Test(ref ClassA class)

{

return class.name;

}

我的理解是这样强制转换应该没有什么问题的,但是上面的代码仍然无法通过编译,提示说参数必须为lvalue。郁闷... 哪位大虾遇到过同样的问题啊?

posted on 2004-04-28 18:24 xlzhu 阅读(2145) 评论(11)  编辑 收藏 所属分类: C#

评论

#1楼    回复  引用    

你写的代码怎么这么难看啊?
2004-04-28 19:17 | Ninputer [未注册用户]

#2楼    回复  引用  查看    

老兄!您太强了!能不能断行啊?你不断行的话,下次我给您竖着回复。
2004-04-28 21:47 | sumtec      

#3楼    回复  引用  查看    

这个确实是一个有趣的例子,有时候让人以为只要B派生自A,那么所有应该是类型A的地方都可以传送一个类型B。其实这个是一个误解,我问你,如果代码是这样的:
ClassB b = new ClassB();
Test(ref b);

void Test(ref ClassA obj)
{
obj = new ClassA();
}

那么是否等价于:
ClassB b = new ClassB();
b = new ClassA();
您认为这个是可能的吗?不可能,对吧!因为你的变量类型限制了这个可能性!请您记住:
1、有类型的不仅仅是事例,变量也有类型。
2、事例的类型和变量的类型是两码事,分别有自己的制约规则。
3、不要用保留字作为标识符,那么多单词不好用非要用class?
4、发完帖子记得看一下是什么样的,像这一次没有任何断行,那就糗大了!

上面的代码如果改成这样,则可以行得通:(为什么自己思考一下)
ClassA a = new ClassB();
Test(ref a);

void Test(ref ClassA obj)
{
obj = new ClassA();
}
2004-04-28 22:06 | sumtec      

#4楼    回复  引用    

sumtec 精辟,都被你说完了

#5楼    回复  引用  查看    

诸位,实在是不好意思,昨天赶项目发完没看就闪了,没有预览的说....

sumtec讲得很有道路,不过可能不适合我,呵呵,以下是我实际的场景:
我封装了微软的DataAccess Application Block类,在其中使用了一个方法-FillDataSet(ref SqlDataAdapter adapter,ref DataSet dataset),为什么要使用这种方法呢?因为我在引用这个类的地方都使用了SqlDataAdapter的TableMapping,其他静态方法都没有实现。如果正常引用都也罢了,可是在我的类中,发现有些类竟然是从DataSet继承的,这个时候就出现了上述问题...
当然,来一个临时DataSet调用完成在转换回来也可以解决这个问题,但是我还没有评估性能损失。
2004-04-29 10:21 | xlzhu      

#6楼    回复  引用  查看    

这是语法规则不是你想不想要的问题,你以为的那种情况部成立啊
2004-04-29 18:28 | Meyer      

#7楼    回复  引用  查看    

我觉得你直接用:
FillDataSet(SqlDataAdapter adapter,DataSet dataset)

不需要用ref的呀,用ref只限于要改变引用本身的情况。FillDataSet如果只要想填充dataset的话,不用ref,被传入的dataset也被改变了。

public void Foo (ref Object o)
{
o = new Object();
}

当调用时:

Object o1 = new Object();
Object o2 = o1;
Foo(o2);

//到这里的时候o2已经不指向o1所指向的对象了,而是指向在Foo()中新创建的那个对象。

而反过来,不需要将传入的引用指向新的对象,而只想改变引用所指对象的内容的时候,不需要用ref,比如:

class Msg
{
public string message;
}

public void Foo(Msg m)
{
m.message = "Changed by Foo";
}

调用的时候:

Msg msg = new Msg;
msg = "Before Foo";
Foo(msg);

//这里msg.message已经变成了"Changed by Foo"


2004-04-30 14:28 | Justin Shen      

#8楼    回复  引用    

引用类型还用ref吗?

它默认就是传地址的改成这样就可了

using System;

public class A
{
public string name;
}

public class B : A
{
}

public class C
{
public static void Main()
{
B b = new B();
b.name = "I'm class b";
//如果用Test(ref b)的话,编译会提示无法转换ClassB到ClassA
Console.WriteLine(Test(b));
Console.WriteLine(b.name);
}

public static string Test(A classA)
{
string temp = classA.name;
classA.name = "I'm not class b";
return temp;
}
}
2006-02-26 19:43 | york [未注册用户]

#9楼    回复  引用    

你的这个问题解决了吗? 我也要解决这个问题 .

#10楼    回复  引用    

我在remoting 中使用 filldataset ,也是使用 sql helper .
以前使用 untyped dataset ,考虑到typed dataset 能够一次设置,多次使用.
减少界面设置字段的麻烦.

#11楼    回复  引用    

Test
2007-10-03 11:22 | E-Sorl [未注册用户]

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2004-05-22 11:28 编辑过


相关链接: