2016-10-11 1 views
3

Это указывает на мой last question, который, кажется, был оставлен. Я испытываю странную «ошибку», если вы будете с C# и MS VS 2015. Чтобы воспроизвести ошибку, выполните следующие действия:C# - Odd Null Reference Исключение во время тестирования, почему это происходит?

  1. Открыть проект приложения консоли и скопировать код вставки ниже.
  2. Установить точку останова здесь: enter image description here
  3. Код первого запуска после точки останова, он работает! : D
  4. Затем запустите код еще раз, но на этот раз СТОП в точке разрыва и ТЯНИТЕ выполняющую заявление курсор INTO, если заявление здесь: enter image description here сюда: enter image description here

Хит Continue и исключение Nre бросается. Почему это происходит? Это только я? Для чего это техническое объяснение?

КОД:

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace testapp 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      FILECollection randomCollection = new FILECollection(); 
      // Fill with junk test data: 
      for(int i = 0; i<10; i++) 
      { 
       FILE junkfile = new FILE() { fileName = i.ToString(), folderName = i.ToString(), fileHashDigest = new byte[1] }; 
       randomCollection.Add(junkfile); 
      } 

      if (true) 
      { 
       Console.WriteLine("testing this weird exception issue..."); 
       FILE test; 
       test = new FILE(); 
       test.fileName = "3"; 
       test.folderName = "3"; 
       test.fileHashDigest = new byte[1]; 

       FILE exists = randomCollection.Where(f => f.fileName == test.fileName && 
               f.fileHashDigest.SequenceEqual(test.fileHashDigest)).First(); 
      } 
     } 
    } 


    public class FILE 
    { 
     public FILE() { _fileName = "";} 
     private string _fileName; 
     public string fileName 
     { 

      get 
      { 
        if (false) 
         return this._fileName.ToUpper(); 
        else 
         return this._fileName; 
      } 
      set 
      { 

        if (false) 
         this._fileName = value.ToUpper(); 
        else 
         this._fileName = value; 
      } 
     } 
     public string folderName { get; set; } 
     public byte[] fileHashDigest { get; set; } 
    } 

    public class FILECollection : IEnumerable<FILE>, ICollection<FILE> 
    { 
     private HashSet<FILE> svgHash; 
     private static List<FILE> PreallocationList; 
     public string FileName = "N/A"; 

     /// <summary> 
     /// Default Constructor, will not 
     /// preallocate memory. 
     /// </summary> 
     /// <param name="PreallocationSize"></param> 
     public FILECollection() 
     { 
      this.svgHash = new HashSet<FILE>(); 
      this.svgHash.Clear(); 
     } 

     /// <summary> 
     /// Overload Constructor Preallocates 
     /// memory to be used for the new 
     /// FILE Collection. 
     /// </summary> 
     public FILECollection(int PreallocationSize, string fileName = "N/A", int fileHashDigestSize = 32) 
     { 
      FileName = fileName; 
      PreallocationList = new List<FILE>(PreallocationSize); 
      for (int i = 0; i <= PreallocationSize; i++) 
      { 
       byte[] buffer = new byte[fileHashDigestSize]; 
       FILE preallocationSVG = new FILE() 
       { 
        fileName = "", 
        folderName = "", 
        fileHashDigest = buffer 
       }; 
       PreallocationList.Add(preallocationSVG); 
      } 
      this.svgHash = new HashSet<FILE>(PreallocationList); 
      this.svgHash.Clear(); // Capacity remains unchanged until a call to TrimExcess is made. 
     } 

     /// <summary> 
     /// Add an FILE file to 
     /// the FILE Collection. 
     /// </summary> 
     /// <param name="svg"></param> 
     public void Add(FILE svg) 
     { 
      this.svgHash.Add(svg); 
     } 

     /// <summary> 
     /// Removes all elements 
     /// from the FILE Collection 
     /// </summary> 
     public void Clear() 
     { 
      svgHash.Clear(); 
     } 


     /// <summary> 
     /// Determine if the FILE collection 
     /// contains the EXACT FILE file, folder, 
     /// and byte[] sequence. This guarantees 
     /// that the collection contains the EXACT 
     /// file you are looking for. 
     /// </summary> 
     /// <param name="item"></param> 
     /// <returns></returns> 
     public bool Contains(FILE item) 
     { 
      return svgHash.Any(f => f.fileHashDigest.SequenceEqual(item.fileHashDigest) && 
            f.fileName == item.fileName && 
            f.folderName == item.folderName); 
     } 

     /// <summary> 
     /// Determine if the FILE collection 
     /// contains the same file and folder name, 
     /// byte[] sequence is not compared. The file and folder 
     /// name may be the same but this does not guarantee the 
     /// file contents are exactly the same. Use Contains() instead. 
     /// </summary> 
     /// <param name="item"></param> 
     /// <returns></returns> 
     public bool ContainsPartially(FILE item) 
     { 
      return svgHash.Any(f => f.fileName == item.fileName && 
            f.folderName == item.folderName); 
     } 

     /// <summary> 
     /// Returns the total number 
     /// of FILE files in the Collection. 
     /// </summary> 
     public int Count 
     { get { return svgHash.Count(); } } 

     public bool IsReadOnly 
     { get { return true; } } 

     public void CopyTo(FILE[] array, int arrayIndex) 
     { 
      svgHash.CopyTo(array, arrayIndex); 
     } 

     public bool Remove(FILE item) 
     { 
      return svgHash.Remove(item); 
     } 

     public IEnumerator<FILE> GetEnumerator() 
     { 
      return svgHash.GetEnumerator(); 
     } 

     IEnumerator IEnumerable.GetEnumerator() 
     { 
      return svgHash.GetEnumerator(); 
     } 
    } 
} 

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

enter image description here

+0

Возможный дубликат [Что такое исключение NullReferenceException и как его исправить?] (http://stackoverflow.com/questions/4660142/what-is-a- nullreferenceexception-and-how-do-i-fix-it) – mybirthname

+1

Вам, ребята, не хватает смысла, я понимаю, что это NRE, но он ТОЛЬКО бросается, когда вы используете отладку э. Это не проблема с кодом (я знаю). –

+2

В чем проблема? Я ожидал бы Null Reference Exception для теста в часах, потому что он еще не был создан. Поместите свою точку останова после теста = новая строка FILE() –

ответ

4

OK вот моя догадка ..

Во-первых, как я уже говорил в комментариях, исключение не возникает, если вы закомментировать строку FILE exists = randomCollection.Where(f => f.fileName == test.fileName && f.fileHashDigest.SequenceEqual(test.fileHashDigest)).First()‌​;

Во-вторых, я заметил такое же поведение можно воспроизвести с помощью следующего кода:

if (true) 
{ 
    object o; 
    o = new object(); 
    Func<bool> m =() => o == null; 
} 

т.е. причина, по-видимому, связана с вариацией способный использоваться в лямбда-выражении. Так, глядя на тот же фрагмент кода выше в ILSpy я получаю следующее:

Program.<>c__DisplayClass0_0 <>c__DisplayClass0_ = new Program.<>c__DisplayClass0_0(); 
<>c__DisplayClass0_.o = new object(); 
Func<bool> func = new Func<bool>(<>c__DisplayClass0_.<Main>b__0); 

так что моя догадка, что NullReferenceException относится к <>c__DisplayClass0_ входом в инстанс быть null - и я поэтому склонен полагать, что пошагового if(true) фактически пропустил первую строку, где был создан <>c__DisplayClass0_

+1

После некоторой отладки с надлежащими смещениями IL, я полностью согласен с вашим заключением. Потому что нет 'nop' между' L_0003: stloc.s flag' и 'L_0005: newobj instance void testapp.Program/<> c__DisplayClass1 ::. Ctor()', к которым Visual Studio может перейти в режим отладки, это просто пропускает создание '<> c__DisplayClass1'. Следующий доступный 'L_000b: nop' находится непосредственно перед строкой' new object() '. («Nops» - это место в режиме отладки, где VS может установить точки останова или перейти к перетаскиванию текущего оператора.) Это поведение очень интересно и немного похоже на ошибку в компиляторе ... – haindl

+1

Я отправил эту проблему для бывшего разработчика Microsoft, который буквально возглавляет команду разработчиков для компилятора C#. Это был его ответ: «Когда вы динамически перемещаете точку выполнения в отладчике, нет никакой гарантии, что ваша программа продолжит работу, как ожидалось. Компилятор генерирует код, предполагающий, что код будет запущен нормально. Если вы нарушите это предположение, тогда могут произойти плохие вещи; быть очень счастливым, что самое худшее, что произошло, было исключение с нулевой ссылкой. ' –

+0

продолжение:' Компилятору не требуется генерировать код, который является прочным перед лицом перемещения по точке управления по вашей прихоти, а отладчик не требуется делать больше, чем добросовестное усилие, чтобы переместить точку контроля вокруг, предполагая, что вы знаете, что вы делаете, и каковы будут последствия. ' –

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