Я нашел странное поведение в VS2015. Подробности:Почему необязательные параметры передаются неверными значениями в Visual Studio 2015?
У меня есть проект .Net 4.6, ссылающийся на сборку 3.5. Эта сборка определяет в одном из своих интерфейсов следующий метод, который я смог проверить с помощью декомпилятора Resharper.
void WriteString([MarshalAs(UnmanagedType.BStr), In] string data, [In] bool flushAndEND = true);
Прими к сведению последнего необязательного аргумента flushAndEND
, который имеет значение по умолчанию true
. Проблема теперь в том, что когда я использую этот метод в своем проекте, зависание над именем метода показывает обычный VS toolTip, который детализирует подпись метода, за исключением того, что для меня это показывает неправильное значение по умолчанию необязательного аргумента flushAndEND
. Вот скриншот
Чтобы сделать вещи еще хуже, я заметил, что во время выполнения, при вызове метода WriteString
только с первым параметром, flushAndEND
получает значение false
, а не его значение по умолчанию определяется в DLL Я ссылаюсь. Воздействие этого на наш проект было большим, потому что оно оказало большую особенность нашего приложения бесполезным и заблокировало большую часть наших регрессионных тестов.
Мне удалось преодолеть эту проблему, вызывая значение необязательного аргумента true при вызове метода, но я боюсь, что в проекте есть другие вызовы, которые страдают от одной и той же проблемы. Поэтому мне понадобится лучшее решение для этого или, по крайней мере, понять, в чем причина такого поведения.
Мы только что обновили нашу среду несколько недель назад. До того, как мы использовали VS2013, все работало нормально.
Мне известно о confirmed .Net 4.6 bug, в результате чего некоторые аргументы передаются неверными значениями, и я могу связать их с моей проблемой здесь, но, как говорится в статье, ошибка возникает только при компиляции для архитектуры x64. Мой проект - это приложение WPF, и мы скомпилируем его как x32.
Почему WriteString
вызван с неправильным аргументом по умолчанию?
Я попробую позже, чтобы изолировать проблему в небольшом проекте и посмотреть, могу ли я воспроизвести проблему.
EDIT: Мне удалось изолировать проблему и найти интересный материал!
Я создал простой .Net 4.6 консольное приложение, добавил ссылку на мой Dll и написал следующий простой код, которые состоят из посылки команды на устройство и читать ответ:
private static void Main(string[] args)
{
//Init managers
ResourceManager ioMgr = new ResourceManagerClass();
FormattedIO488 instrument = new FormattedIO488Class();
//Connect to the USB device
instrument.IO = (IMessage)ioMgr.Open("USB0::0x0957::0x0909::MY46312358::0::INSTR");
string cmd = "*IDN?";
//This is the problematic method from my dll
instrument.WriteString(cmd);
//Read the response
string responseString = instrument.ReadString();
Console.WriteLine(responseString);
Console.ReadKey();
}
Что я сделал следующий, открыт этот проект как с VS 2013, так и с VS 2015. В обеих версиях VS я перестраивал проект и запускал его. Вот результаты:
VS2013: WriteString
была вызвана с помощью ПРАВИЛЬНОГО значения по умолчанию flushAndEND
(который true
значение очистки буфера и завершение команды).
VS2015: WriteString
был вызван с использованием значения WRONG по умолчанию flushAndEND
, которое дало исключение таймаута.
Дальнейшие проверки между двумя версиями Visual Studio показывает, что объект зритель браузер VS2013 показывает сигнатуру метода, как:
void WriteString(string data, [bool flushAndEND = True])
в то время как браузер объектов в VS2015 показывает сигнатуру метода, как:
void WriteString(string data, [bool flushAndEND = False])
Единственное объяснение этого поведения заключается в том, что проблема с компилятором VS2015 не считывает правильные значения по умолчанию из сборки.
Erm, поэтому IntelliSense показывает это как * false *, и компилятор интерпретирует его как * false *, это только декомпилятор Resharper, который показывает * true *. Как это не ошибка Resharper? Похоже на COM-компонент, обновите библиотеку interop, запустив .NET-версию Tlbimp.exe. –
. Верю, что правильное значение по умолчанию должно быть истинным, потому что это означает, что нужно записывать в буфер и немедленно скрывать его. И да, это компонент COM. Я попробую ваше предложение как можно скорее. – disklosr
@HansPassant Можете ли вы показать, как использовать инструмент Tlbimp.exe? Благодаря! – disklosr