【问题标题】:C# and override operator with refC# 并用 ref 覆盖运算符
【发布时间】:2016-11-01 15:18:00
【问题描述】:

看看这段代码:

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 作为参数:

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;
}

和变化,但没有成功。

有没有人遇到过这个问题并有解决办法?

谢谢, 萨萨卡伊奇

【问题讨论】:

  • boperator classA(classB val) 的返回值的引用绝不是对b 的引用。假装它是只会引起混淆,因为您将它传递给它的方法将改变一个临时值,该值将在方法返回时消失。然后你会在这里问我们是否有解决那个问题的方法。如果看起来像 f(ref b) 的东西实际上是 f(lolwut),这对任何人都没有好处
  • 如你所见,ClassB 中的 someA 不是临时的,也永远不会是。
  • 我需要来自 B 的 ref,因为我希望它被更改并且仍然是 B 的一部分,所以单独的 'afromb' 不是解决方案。
  • 它是临时的,因为您正在从一个隐式转换到另一个,您无法引用它,因为它不再以该形式存在。
  • 正如您应该能够推断的那样,C# 设计团队并不认为编译器的工作是分析运算符并为您找出答案。

标签: c# overriding operator-keyword ref


【解决方案1】:

如果你想通过引用传递它,你需要有一个完全类型的变量ClassA。该变量的当前值可以是ClassB 的实例,但变量 的类型需要是ClassA

classA a = new classA();
classA b = new classB();

testByRef(ref b);  

这将编译。这需要发生,因为testByRef 可以为var 分配一个值,并且该值可以是ClassA 类型的任何值,它可能不是ClassB 实例,因此您不能提供类型变量ClassB.

隐式转换运算符将始终返回一个。它不能返回一个变量,这是你在那个操作符中试图用ref 做的。没有办法支持这一点。

还值得注意的是,您的 testByRef 方法实际上并没有改变变量 var,因此没有理由实际通过引用传递它。

最后,你真的不应该通过改变传入的操作数来做你在原始隐式运算符实现中所做的事情。这非常令人困惑用户;隐式运算符应该创建您要转换为的类型的新实例而不以任何方式更改原始对象

【讨论】:

  • testbyref 就是这样,测试函数。真正的功能正在改变它。
  • 并且 ClassB 通过引用传递给我的“调用测试”函数,因此我无法将其更改为 ClassA。
  • ClassB 就是这样设计的,所以它会根据当时的状态应用程序“改变”,所以它可以是“工作”、“连接”、“传输”或“任何东西”,带有适当的信息等。
  • @Kajko 您可能会尝试的一种方法是找出人们在您所做的任何事情上通常使用的设计模式,并以常规方式实现它。
  • @Kajko 所以听起来你想要改变对象,而不是改变变量,以便 one 对象实例的状态发生变化。如果您只想创建具有新状态的新对象,您可能应该只是返回它们;然后,调用者可以根据需要将其分配给它传入的同一个变量,或者它可以做任何它想做的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-30
  • 2010-12-26
  • 1970-01-01
  • 2010-10-13
  • 1970-01-01
相关资源
最近更新 更多