Возможная ошибка компилятора C # 4.0, другие могут проверить? - PullRequest
10 голосов
/ 01 августа 2010

Поскольку я не знаю точно, какая его часть вызывает ошибку, я не совсем уверен, как ее лучше обозначить.

Этот вопрос является побочным продуктом вопроса SO *Код 1003 * c #, похоже, оптимизирован недопустимым образом, так что значение объекта становится нулевым , что я пытался помочь Гари вчера вечером.Он был тем, кто обнаружил, что есть проблема, я просто уменьшил проблему до более простого проекта и хочу проверить, прежде чем я продолжу его, отсюда этот вопрос.

Я выложузаметка о Microsoft Connect, если другие могут проверить, что они тоже сталкиваются с этой проблемой, и, конечно, я надеюсь, что Джон, Мэдс или Эрик тоже посмотрят на нее:)

Это включает в себя:

  • 3 проекта, 2 из которых являются библиотеками классов, один из которых является консольной программой (последний не нужен для воспроизведения проблемы, но только выполнение этого показывает проблему, тогда как вам нужно использовать рефлектори посмотрите на скомпилированный код, если вы его не добавляете)
  • Неполные ссылки и вывод типа
  • Обобщения

Код доступен здесь: репозиторий кода .

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

Проблема проявляется при создании инвalid приведен в вызове метода перед возвратом простого универсального списка, приведение его к чему-то странному перед возвратом.Исходный код закончился приведением к логическому значению, да, логическому.Компилятор добавил приведение из List<SomeEntityObject> к логическому значению, прежде чем вернуть результат, и сигнатура метода сказала, что вернет List<SomeEntityObject>.Это, в свою очередь, приводит к странным проблемам во время выполнения, все из-за того, что вызов метода считается «оптимизированным» (исходный вопрос), или сбой с BadImageFormatException или InvalidProgramException или одним из подобных исключений.

Во время моей работы по воспроизведению этого я видел приведение к void[], и текущая версия моего кода теперь приводится к TypedReference.В одном случае происходит сбой Reflector, так что, скорее всего, в этом случае код был вне надежды.Ваш пробег может варьироваться.

Вот что нужно сделать, чтобы воспроизвести его:

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

Я прошу прощения за экранированные символы html в приведенном ниже коде, это Маркдаун подшучивает над мной,если кто-нибудь знает, как я могу это исправить, сообщите мне об этом или просто отредактируйте вопрос

  1. Создайте новое решение Visual Studio 2010, содержащее консольное приложение, для .NET 4.0
  2. Добавьте два новых проекта, оба библиотеки классов, а также .NET 4.0 (я собираюсь предположить, что они называются ClassLibrary1 и ClassLibrary2)
  3. Настройте все проекты для использования полной среды выполнения .NET 4.0,не только профиль клиента
  4. Добавление ссылки в консольном проекте в ClassLibrary2
  5. Добавление ссылки в ClassLibrary2 в ClassLibrary 1
  6. Удалите два добавленных файла Class1.csпо умолчанию в библиотеки классов
  7. В ClassLibrary1 добавьте ссылку на System.Runtime.Caching
  8. Добавьте новый файл в ClassLibrary1, назовите его DummyCache.cs и вставьте следующий код:

    using System;
    using System.Collections.Generic;
    using System.Runtime.Caching;
    
    namespace ClassLibrary1
    {
        public class DummyCache<TModel> where TModel : new()
        {
            public void TriggerMethod<T>()
            {
            }
            // Try commenting this out, note that it is never called!
            public void TriggerMethod<T>(T value, CacheItemPolicy policy)
            {
            }
            public CacheItemPolicy GetDefaultCacheItemPolicy()
            {
                return null;
            }
            public CacheItemPolicy GetDefaultCacheItemPolicy(IEnumerable<string> dependentKeys, bool createInsertDependency = false)
            {
                return null;
            }
        }
    }
    
  9. Добавьте новый файл в ClassLibrary2, назовите его Dummy.cs и вставьте следующий код:

    using System;
    using System.Collections.Generic;
    using ClassLibrary1;
    
    namespace ClassLibrary2
    {
        public class Dummy
        {
            private DummyCache<Dummy> Cache { get; set; }
            public void TryCommentingMeOut()
            {
                Cache.TriggerMethod<Dummy>();
            }
            public List<Dummy> GetDummies()
            {
                var policy = Cache.GetDefaultCacheItemPolicy();
                return new List<Dummy>();
            }
        }
    }
    
  10. Вставьте следующий код в Program.cs в консольном проекте:

    using System;
    using System.Collections.Generic;
    using ClassLibrary2;
    
    namespace ConsoleApplication23
    {
        class Program
        {
            static void Main(string[] args)
            {
                Dummy dummy = new Dummy();
                // This will crash with InvalidProgramException
                // or BadImageFormatException, or a similar exception
                List<Dummy> dummies = dummy.GetDummies();
            }
        }
    }
    
  11. Постройте и убедитесь, что нет ошибок компилятора

  12. Теперь попробуйте запустить программу. Это должно произойти с одним из самых ужасных исключений. Я видел и InvalidProgramException, и BadImageFormatException, в зависимости от того, что приведение закончилось как
  13. Посмотрите на сгенерированный код Dummy.GetDummies в Reflector. Исходный код выглядит так:

    public List<Dummy> GetDummies()
    {
        var policy = Cache.GetDefaultCacheItemPolicy();
        return new List<Dummy>();
    }
    

    Однако рефлектор говорит (для меня это может отличаться в том, какой актер выбрал для вас, и в одном случае Рефлектор даже разбился):

    public List<Dummy> GetDummies()
    {
        List<Dummy> policy = (List<Dummy>)this.Cache.GetDefaultCacheItemPolicy();
        TypedReference CS$1$0000 = (TypedReference) new List<Dummy>();
        return (List<Dummy>) CS$1$0000;
    }
    

Теперь, вот несколько странных вещей, приведенный выше сбой / неверный код:

  • Библиотека2, которая имеет Dummy.GetDummies, выполняет вызов для получения политики кэширования по умолчанию для класса из Библиотеки1. Он использует вывод типа var policy = ..., и в результате получается объект CacheItemPolicy (ноль в коде, но тип важен).

    Однако ClassLibrary2 не имеет ссылки на System.Runtime.Caching, поэтому он не должен компилироваться.

    И действительно, если вы закомментируете метод в Dummy с именем TryCommentingMeOut, вы получите:

    Тип 'System.Runtime.Caching.CacheItemPolicy' определен в сборке, на которую нет ссылок. Необходимо добавить ссылку на сборку 'System.Runtime.Caching, Version = 4.0.0.0, Culture = нейтральный, PublicKeyToken = b03f5f7f11d50a3a'.

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

  • Существует аналогичный метод в DummyCache, если вы восстанавливаете метод в Dummy, так что код снова компилируется, а затем закомментируйте метод в DummyCache, который имеет «Попробуйте комментировать это над комментарием, вы получаете ту же ошибку компилятора

1 Ответ

2 голосов
/ 01 августа 2010

ОК, я загрузил ваш код и могу подтвердить проблему, как описано.

Я не проделывал никаких обширных попыток с этим, но когда я запускаю & отражатель сборки Release, все кажется в порядке (= исключение null ref и чистая разборка).
Отражатель (6.10.11) аварийно завершил сборку Debug.

Еще один эксперимент: я задумался об использовании CacheItemPolicies, поэтому заменил его на свой собственный MyCacheItemPolicy (в 3-м классе), и всплыло то же исключение BadImageFormat.

В исключении упоминается: {"Неверная двоичная подпись. (Исключение из HRESULT: 0x80131192)"}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...