我相信这是一个非常简单的问题。任何人都可以解释为什么这段代码输出1000而不是1050
public class Program
{
public static void Main()
{
Bus b = new Bus(1000);
((Car)b).IncreaseVolume(50);
Console.WriteLine(b.GetVolume());
}
}
public interface Car
{
int GetVolume();
void IncreaseVolume(int amount);
}
public struct Bus : Car
{
private int volume;
public Bus(int volume)
{
this.volume = volume;
}
public int GetVolume()
{
return volume;
}
public void IncreaseVolume(int amount)
{
volume += amount;
}
}
}
答案 0 :(得分:8)
将值类型(struct
)转换为接口框的值。所以你要在值的盒装副本上调用方法,而不是在值本身上调用。
答案 1 :(得分:1)
值类型(struct
)按值传递,但接口被视为引用类型(不是值类型)。我们来看看:
Bus b = new Bus(1000);
现在b
包含Bus
的值,其音量设置为1000.
Car c = (Car)b;
现在b
中的值被复制并成为Car
的引用类型(盒装)。现在c
包含指向盒装副本的指针。
c.IncreaseVolume(50);
在引用类型上,您调用IncreaseVolume
,它是Car
接口的成员。它接收对盒装值的引用。它需要一个指向框中值的托管指针(使其再次成为值类型)。
void Car.IncreaseVolume(int amount)
{
((Bus)this).IncreaseVolume(amount);
}
现在,您的方法将对框中的值执行操作:
public void IncreaseVolume(int amount)
{
volume += amount;
}
现在该方法返回。请注意,b
中的值只对其副本执行了操作。所以下一个语句将打印1000
:
Console.WriteLine(b.GetVolume());
就是这样。
答案 2 :(得分:0)
虽然有时值类型可以用来实现变异接口,但必须非常谨慎地使用这些类型。 C#假装所有值类型都是对象的事实在这方面有点无益(实际上,它们是 convertible 到Object
的东西),因为它意味着没有办法使编译器警告不正确的用法。
除了完全忽略接口的选项之外,通常需要使用变异接口类型的代码必须执行以下两种操作之一:
在大多数情况下,如果需要某些东西来实现变异的接口,那么所讨论的类型应该是一个类。可变结构通常只允许通过直接修改底层字段或使用对ref
传递的实例进行操作的静态方法来实现突变。