Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 引用传递对象与cs1690之间的冲突_C#_Object_Ref - Fatal编程技术网

C# 引用传递对象与cs1690之间的冲突

C# 引用传递对象与cs1690之间的冲突,c#,object,ref,C#,Object,Ref,此代码已更新。 Robot.cs: struct state systemcheck() { state stateInfo = new state(); public double x,y,z; } Main.cs: public state stateInfo; private readonly Sub cpnew; public Main() { InitializeComponent(); cpnew = new Sub(this); } Sub.cs: public s

此代码已更新。 Robot.cs:

 struct state systemcheck()
 {
 state stateInfo = new state();
 public double x,y,z; 
 }
Main.cs:

public state stateInfo;
private readonly Sub cpnew;
public Main()
{
InitializeComponent();
cpnew = new Sub(this);
}
Sub.cs:

public state systinfo;
private readonly Main main;
public Sub(Main main)
{
InitializeComponent();     
this.main = main;
systinfo = this.main.stateInfo; 
} 
这里,
systinfo.X
提供了一个空值。但是
mainfrm.stateInfo.X
提供了正确的值,但抛出了引用封送类警告。
初始化systinfo的正确方法是什么?
state
的值是从外部连接的机器人获得的

这是你要求的一件好事-记住,除非你完全知道自己在做什么,否则一定要遵守警告。在这种情况下,你肯定不知道自己在做什么

表单
是一个
——所有类都是.NET中的引用类型。这有几个含义,其中一个在这里非常相关——它们总是通过引用传递。换句话说,当您使用
Main
作为参数时,您已经在传递引用(类似于在C中传递指向
Main
的指针)

使用
ref
,将引用传递给引用。这允许您从方法内部修改外部引用。这不是您想要的-作为一个简单的示例,它允许您编写一个增量方法:

public void Increment(ref int value)
{
  value = value + 1;
}
如果未使用
ref
,则只需修改
value
的本地值即可。使用
ref
,它修改调用者中的本地值

在您的情况下,正确的代码将更接近

public state stateInfo;
private readonly Sub cpnew;
public Main()
{
    InitializeComponent();

    cpnew = new Sub(this);
}
表格2:

public state systinfo;
private readonly Main main;
public Sub(Main main)
{
    InitializeComponent();      
    this.main = main;
    systinfo = mainfrm.stateInfo; 
} 
那么,警告告诉了你什么<代码>表单继承自
MarshalByRefObject
。这意味着您可能实际上没有传递真正的
表单
对象-例如,您完全可能只有远程计算机上的
表单
的代理。这意味着对类型的所有调用都会通过代理自动封送,在实际实例上执行,并返回结果。由于
state
是一个
struct
(我打赌这是因为您不理解C#的
struct
和C的
struct
之间的区别),它是一种值类型-如果您确实持有代理而不是真实实例,这将导致运行时异常

为了避开警告,您可以先将
状态
复制到本地,这样可以确保安全(更重要的是,显而易见)

当你从C++到C语言时,你会掉进很多陷阱,它们看起来很相似,但是有很多不同之处。在你实际操作之前,试着查一下你试图使用的任何东西。例如,查找<代码> REF 关键字会使你明显地指向指针,并且查找<代码> Stutt和类< /C> >,告诉你,它们的行为与C++完全不同。小心点


用C#编写习惯用法变得更加严重。例如,您通常在需要的地方创建子窗体和对话框,而不是在构造函数中创建实例并在需要时重用它。当然,循环引用通常是一个糟糕的想法——它是增加代码复杂度的一个好方法,并且它使调试和测试更加昂贵。进一步的重构对循环引用的伤害更大。

请提供一个完整有效的示例
public void state systinfo
显然是无效的,您的示例中还有其他方面很难理解。如果您可以遵循.NET命名约定,那么它也会更清晰。从
public Sub(ref Main)
中去掉
ref
。在C++语句中,您的代码通过一个指针传递给代码< main >代码>,这不是您想在这里做的。@当我实现“CPNe=新的子(REF main)”时,自动地构造了DavidArno:<代码>公子子(REF main main)< /C> >;此外,当我试图修改它时,它会抛出一个错误。谢谢你的回复。但问题依然存在
systinfo.X
仍然生成空值,
mainfrm.stateInfo
虽然生成输出,但抛出CS1690异常(通过引用封送)。@srivas为什么不应该是
null
?你从来没有初始化过它。我是这样初始化它的:
public Sub(Main Main){InitializeComponent();this.Main=Main;systino=new state();systino=mainfrm.stateInfo;}
@srivas你可能没有意识到这一点,但你只是创建了一个新实例(fine),将它分配给一个字段(fine),然后立即将其替换为来自
mainfrm
的统一化对象。请推荐初始化对象(
systinfo
)的正确方法,该方法涵盖了由于直接调用(
mainfrm.stateinfo
)而导致的引用覆盖marshall的方面。对不起,我犯了一个很大的错误。此处,
mainfrm
main
处于启用状态,并且相同。