【问题标题】:How a variable can have two values at the same time?一个变量如何同时具有两个值?
【发布时间】:2012-01-09 01:57:48
【问题描述】:

我想对于我要写的内容,我应该首先澄清一下,这不是我想要实现的目标。这是发生在我身上的事情,我正在尝试了解它是如何可能的,所以我可以解决它。所以我们开始...

我正在使用 C#、.Net 4.0。代码很大,太大了,无法在这里全部列出,但我尝试解释发生了什么,希望有知识渊博的人有一些想法。

在我的调用堆栈中,我有一系列通用方法,我注意到虽然值应该只是从一个传递到另一个,但它正在发生变化。好吧,这是我的第一印象。后来我设法隔离了一种有问题的方法,当我停下来时,我可以看到对象的同一属性有两个不同的值。

public class Sample : BaseClass, ISomeInterface
{
    [XmlIgnore]
    public new Guid Id { get; set; }
} 

BaseClass 和 ISomeINterface 定义的重要意义

public Guid Id

所以现在,当我停止在该通用方法中并观察 Sample 类型的变量 data 时,我可以展开它的属性并查看 Id。但是当我观看 data.Id 时,它显示出不同的价值。看看你自己。

(这是一张我无法发布的图片,因为名声微不足道。抱歉)

编辑:我把它推到了http://picturepush.com/public/7307446

有没有人知道Watch 窗口中这些值的获取方式有何不同?有什么区别?我尝试了许多不同的方法,铸造,使用反射,但我得到的值总是与你观看 data.Id 时的值相同,具有讽刺意味的是,正确的值,我期望的是另一个,难以捉摸的值。

哦,不,这不是家庭作业;)

【问题讨论】:

  • 请把图片上传到其他地方。
  • BaseClass 是什么样的?当您查看值是 Sample 类实例转换为 Sample Class 还是 BaseClass 时?
  • 属性是否用 DebuggerDisplayAttribute 修饰?当您在调试器中展开对象时,您可以显示与您看到的不同的值。
  • 图片上传link我已经尝试转换为所有可能的类型无济于事,值总是相同的属性没有用DebuggigerDisplayAttribute修饰但是再次通过代码我注意到ValueInjector之前用于从不同的对象复制值。会不会有副作用?

标签: c# .net visual-studio-debugging


【解决方案1】:

new 关键字隐藏了基类成员。

BaseClass中的Id属性设置为虚拟:

public class BaseClass : ISomeInterface
{
    public virtual Guid Id { get; set; }
}

并在Sample 中覆盖它:

public class Sample : BaseClass, ISomeInterface
{
    public override Guid Id { get; set; }
}

【讨论】:

  • 已经解决了。我可以理解隐藏对开发人员来说是多么令人困惑,但它的存在是有原因的,有时您需要定义(或重新定义)一个属性。但是在这里看起来调试器/编译器/.Net_framework 也被混淆了,但是语言的“特性”;)
【解决方案2】:

当您在基类和实际类中定义 Id 时,第二个定义不会覆盖第一个,而是隐藏它。这意味着 Sample 类实际上包含这两个定义,它取决于您访问的变量的静态类型。

因此:

Sample s = new Sample();
BaseClass b = (BaseClass)s;
s.Id != b.Id;

这通常不是您想要的,并且可能导致非常奇怪的行为,正如您已经发现的那样:)

演示这一点的简单可编译示例:

class A {
    public int val = 5;

    public static void Main(string[] args) {
        B b = new B();
        A a = (A)b;
        Console.WriteLine(a.val); // 5
        Console.WriteLine(b.val); // 10
    }
}

class B : A {
    public int val = 10;
}

如果您已经遇到这种混乱并且无法正确修复它,您可以将静态类型转换为您想要访问的任何版本。

【讨论】:

  • 我考虑过这一点,并尝试强制转换为层次结构中的所有类型,但无济于事。在您的示例中,这两个变量显然属于两种不同的类型。请看我上传的图片,我说的是同一时间的一种类型的一个变量。
【解决方案3】:

不要在Sample 类中定义Id 属性。只需从BaseClass 继承即可。上面的代码应该产生 Sample.Id 隐藏 BaseClass.Id 的编译器警告

【讨论】:

  • 在该 ID 之前有新的。我需要把它放在那里才能用基类中没有的属性来装饰它。
  • 你是对的。我错过了new 关键字。不过,这是您问题的根源。如果您的代码有 BaseClass 类型的引用,您将看到在 BaseClass 中定义的 Id。如果引用的类型为Sample,您将看到新的。如果您无法修改基类,那么您需要确保在使用时处理的是 Sample 类型的引用。
  • 感谢您的意见。当然隐藏是问题的根源,但这个概念本身是众所周知的(对我来说)。真正的问题和混乱的根源是为什么它只发生在一种方法中,以及为什么调试器同时显示两个值。无论如何,现在已经解决了。覆盖而不是隐藏有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 2018-01-10
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
相关资源
最近更新 更多