C#和带有ref的超越运算符
请看以下代码:C#和带有ref的超越运算符,c#,overriding,operator-keyword,ref,C#,Overriding,Operator Keyword,Ref,请看以下代码: public class classA { public string something; public classA() { something = "aaa"; } } public class classB { private classA someA = new classA(); public static implicit operator classA(classB val) {
public class classA
{
public string something;
public classA()
{
something = "aaa";
}
}
public class classB
{
private classA someA = new classA();
public static implicit operator classA(classB val)
{
val.someA.something = "From B";
return val.someA;
}
}
ClassB包含ClassA,作为简化的大小写。
有一个方法(函数,可以随意调用)将ClassA作为param接收:
public void test( classA var)
{
MessageBox.Show(var.something);
}
以及另一种接收ClassA作为ref参数的方法:
public void testByRef( ref classA var)
{
MessageBox.Show(var.something);
}
现在,我已经覆盖了ClassB中的运算符ClassA,所以第一个函数也可以用ClassB调用,但我不知道如何覆盖ClassB中的ref运算符进行第二次调用:
classA a = new classA();
classB b = new classB();
test(a); // Works
test(b); // Works
testByRef(ref a); // Works
testByRef(ref b); // Does not work - error CS1503: Argument 1: cannot convert from 'ref classB' to 'ref classA'
我试过像这样超载
public static implicit operator ref classA(classB val)
{
val.someA.something = "From B";
return val.someA;
}
和变化,但没有成功
有人遇到过这个问题并有解决方案吗
谢谢,
Sasa Kajic如果要通过引用传递,则需要一个类型正好为
ClassA
的变量。该变量的当前值可以是ClassB
的实例,但变量的类型必须是ClassA
classA a = new classA();
classA b = new classB();
testByRef(ref b);
这将编译。这需要发生,因为testByRef
可以为var
赋值,该值可以是ClassA
类型的任何值,并且它可能不是ClassB
实例,所以不能提供ClassB
类型的变量
隐式转换运算符将始终返回一个值。它不能返回一个变量,这是您试图在该运算符中使用ref
执行的操作。没有办法支持这一点
还值得注意的是,您的testByRef
方法实际上并没有对变量var
进行变异,因此没有理由通过引用实际传递它
最后,您真的不应该通过改变传入的操作数来执行您在原始隐式运算符实现中正在执行的操作。这让用户非常困惑;隐式运算符应创建要转换为的类型的新实例,而不以任何方式更改原始对象。如果要通过引用传递,则需要一个类型正好为
ClassA
的变量。该变量的当前值可以是ClassB
的实例,但变量的类型必须是ClassA
classA a = new classA();
classA b = new classB();
testByRef(ref b);
这将编译。这需要发生,因为testByRef
可以为var
赋值,该值可以是ClassA
类型的任何值,并且它可能不是ClassB
实例,所以不能提供ClassB
类型的变量
隐式转换运算符将始终返回一个值。它不能返回一个变量,这是您试图在该运算符中使用ref
执行的操作。没有办法支持这一点
还值得注意的是,您的testByRef
方法实际上并没有对变量var
进行变异,因此没有理由通过引用实际传递它
最后,您真的不应该通过改变传入的操作数来执行您在原始隐式运算符实现中正在执行的操作。这让用户非常困惑;隐式运算符应创建要转换为的类型的新实例,而不以任何方式更改原始对象。引用
b
的运算符classA(classB val)
的返回值决不是对b
的引用。假装它是只会引起混乱,因为您将其传递给的方法将更改一个临时值,该值将在该方法返回时消失。然后你会在这里问我们是否有解决这个问题的办法。如果某个看起来像f(ref b)
的东西实际上是f(lolwut)
,这对任何人都没有好处,正如你所看到的,类b中的某个东西不是临时的,永远不会是。我需要b中的ref,因为我希望它被更改,并且仍然是b的一部分,因此,单独的“afromb”不是解决方案。它是临时的,因为您正在从一个隐式转换到另一个,您无法引用它,因为它不再以该形式存在。您应该能够推断,C#设计团队认为编译器的工作不是分析运算符并为您找出答案。引用b
的运算符classA(classB val)
的返回值绝不是引用b
。假装它是只会引起混乱,因为您将其传递给的方法将更改一个临时值,该值将在该方法返回时消失。然后你会在这里问我们是否有解决这个问题的办法。如果某个看起来像f(ref b)
的东西实际上是f(lolwut)
,这对任何人都没有好处,正如你所看到的,类b中的某个东西不是临时的,永远不会是。我需要b中的ref,因为我希望它被更改,并且仍然是b的一部分,因此,单独的“afromb”不是解决方案。它是临时的,因为您正在从一个隐式转换到另一个,您无法引用它,因为它不再以那种形式存在。您应该能够推断,C#设计团队不认为编译器的工作是分析运算符并为您找出答案。testbyref就是这样,测试功能。真正的函数正在改变它。ClassB通过引用传递给我的“调用测试”函数,因此我不能将其更改为ClassA。ClassB的设计方式使其根据应用程序当时的状态而“改变”,因此它可以“工作”,或“连接”或“传输”或“任意”,使用适当的信息等。@Kajko您可以尝试的一种方法是找出人们通常用于您所做的任何事情的设计模式,并按惯例实现它。@Kajko所以听起来您希望改变对象,而不是改变变量,从而改变一个对象实例的状态。如果您只想创建具有新状态的新对象,您可能只需要返回它们;然后,调用方可以根据需要将其分配给传入的同一个变量,也可以执行其他任何操作。testbyref就是测试函数。实函数正在改变它。ClassB通过引用传递给我的“调用测试”函数