2012-01-09 3 views
3

Я предполагаю, что я напишу, я должен сначала уточнить, это не то, чего я хотел бы достичь. Это случилось со мной, и я пытаюсь понять, как это возможно, поэтому я могу это исправить. Итак, вот мы идем ...Как переменная может иметь два значения одновременно?

Я использую C#, .Net 4.0. Код является большим, слишком большим, чтобы пройти все это здесь, но я пытаюсь объяснить, что происходит в надежде, что кто-нибудь знает, кто будет иметь некоторые мысли.

В моем стеке вызовов у меня есть ряд общих методов, и я заметил, что хотя значение должно быть просто передано от одного к другому, оно меняется. Хорошо, это было мое первое впечатление. Позже мне удалось выделить один проблемный метод, в котором при остановке я могу видеть два разных значения для одного и того же свойства объекта.

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

Что может быть значительным, что оба BaseClass и ISomeInterface определяют

public Guid Id 

так что теперь, когда я останавливаюсь в этих родовых методах и смотреть переменные данные из образца типа я могу расширить свои свойства и см. первое значение Id. Но когда я смотрю data.Id, он показывает различное значение. Посмотрите сами.

(Здесь была картина, которую я не могу отправить из-за незначительной репутации Sorry.)

Edit: я толкнул его там http://picturepush.com/public/7307446

ли какой-либо орган, там знают, что такое различие в том, как те значения в окне Часы окна? В чем разница? Я пробовал много разных подходов, кастинг, используя отражение, но всегда получаю значение так же, как при наблюдении data.Id и по иронии судьбы, правильное значение, которое я ожидаю, другое, неуловимое.

О, и нет, это не домашнее задание;)

+0

Загрузить картинку, чтобы где-нибудь еще, пожалуйста. – gdoron

+0

Как выглядит BaseClass? Когда вы проверяете, что значение - это экземпляр класса Sample, выбранный как образец класса или BaseClass? –

+0

Является ли свойство украшено DebuggerDisplayAttribute? Вы можете отобразить другое значение для того, что видите, когда вы расширяете объект в отладчике. –

ответ

5

Ключевое слово new скрывает член базового класса.

Id Установите свойство в BaseClass к виртуальному:

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

и переопределить его в Sample:

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

Это решило. Я могу понять, как скрытие может запутать для разработчиков, но оно существует по какой-то причине, иногда вам нужно определить (или переопределить) свойство. Но здесь похоже, что debugger/compiler/.Net_framework тоже путают, но «особенность» языка;) – michal

2

Не определяет Id свойства в Sample классе. Просто наследуйте его от BaseClass. Приведенный выше код должен производить компилятор предупреждения, Sample.Id скрывается BaseClass.Id

+1

Существует новый перед этим Id. Мне нужно иметь его там, чтобы украсить его атрибутами, которые не находятся в базовом классе. – michal

+0

Вы правы. Я пропустил ключевое слово 'new'. Это источник вашей проблемы. Если у вас есть код типа «BaseClass», вы увидите идентификатор, определенный в BaseClass. Если ссылка имеет тип 'Sample', вы увидите новую. Если вы не можете изменить базовый класс, вам необходимо убедиться, что вы имеете дело с ссылкой типа 'Sample' всякий раз, когда вы его используете. –

+0

Спасибо за ваш вклад. Разумеется, скрытие является источником проблемы, но концепция как таковая хорошо известна (мне). Реальная проблема и источник путаницы были причиной того, что это происходило только в одном методе, и почему отладчик показывал одновременно два значения. В любом случае, это теперь разрешено. Помогло, а не скрывалось. – michal

3

Когда вы определяете Id как в базовом классе и фактического класса, второе определение не перекрывая первый, но скрывается это , Это означает, что класс Sample фактически содержит оба определения и зависит от статического типа переменной, к которой вы обращаетесь.

Следовательно:

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

Это, как правило, не то, что вы хотите, и может привести к весьма странным поведением, как вы уже выяснили :)

Простой compileable пример, демонстрирующий это:

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

Если у вас уже есть этот беспорядок и вы не можете исправить его правильно, вы можете применить статический тип к любой версии, к которой хотите получить доступ.

+0

Я подумал об этом и попробовал кастинг для всех типов в иерархии безрезультатно. В вашем примере две переменные явно имеют два разных типа. Пожалуйста, посмотрите изображение, которое я загрузил, я говорю об одной переменной одного типа в один и тот же момент времени. – michal

 Смежные вопросы

  • Нет связанных вопросов^_^