Pull to refresh

Знаете ли вы как работает этот код?

Reading time3 min
Views945
Вчера, в очередной раз столкнувшись с интересным поведением кода, я решил привести пару примеров из C# и MS SQL, которые в свое время меня удивили.

Пример 1. Меняем местами значения переменных (C#)


С этим поведением я встретился несколько лет назад, когда только начал изучать C#. Применив знакомый метод, чтобы поменять значения 2-х переменных местами, я с удивлением обнаружил, что он не работает.
//Задаем 2 переменные
int x = 1, y = 2;

//Меняем их значения при помощи xor
x ^= y;
y ^= x;
x ^= y;

//Выводим результат [x=2;y=1]
Console.WriteLine("x = {0};y = {1}", x, y);

//Снова меняем их значения, но только пишем все в одну строчку
x ^= y ^= x ^= y;

//Выводим результат [x=0;y=2]
Console.WriteLine("x = {0};y = {1}", x, y);


* This source code was highlighted with Source Code Highlighter.

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

Пример 2. Переводим число в строку (MS SQL)


Вот пример того, как функции cast и convert могут приподносить сюрпризы.
cast(1000 as varchar(3)) --Результатом будет '*'
cast(1000 as nvarchar(3)) --Результатом будет Error


* This source code was highlighted with Source Code Highlighter.

Хотя такое поведение и задокументировано в MSDN, столкнулся я с этим раньше чем прочитал о нем.

Пример 3. Использование NOT IN и IN в условии(MS SQL)


Этот пример также описан в MSDN, но узнал я о таком поведении, только когда из-за него произошла ошибка в программе.
--Создадим тестовую таблицу
create table #tmpTable
(
  id int
)

/*Заполним ее числами от 1 до 10*/

--Теперь выполним пару select'ов
select * from #tmpTable where id in (1,2,null,3)  --Результат: 3 строки
select * from #tmpTable where id not in (1,2,null,3)--Результат: 0 строк

--Не забудем таблицу удалить
drop table #tmpTable


* This source code was highlighted with Source Code Highlighter.

В отличие от IN, который просто пропускает null, NOT IN всегда возвращает пустую выборку. В общем-то, после небольших размышлений, на тему «почему так?», результат уже не кажется необычным.

Пример 4. Finally и необработанное исключение(C#)


Следующая ситуация мне кажется необычной, потому что меняет поведение в зависимости от того, ловите ли вы исключение или нет.
Итак, напишем класс с одним методом, в котором будет блок try-catch-finally. Вызов метода также обернем в try-catch.
class C
{
  public void F()
  {
    try
    {
      Console.WriteLine("Try");
      throw new Exception("some exception");
    }
    catch(Exception ex)
    {
      Console.WriteLine("F Catch");
      throw ex;
    }
    finally
    {
      Console.WriteLine("Finally");
    }
  }
}

static void Main(string[] args)
{
  try
  {
    C c = new C();
    c.F();
  }
  catch (Exception)
  {
    Console.WriteLine("Main catch");
  }      
}


* This source code was highlighted with Source Code Highlighter.

Все сработает так как и должно:
1.Try
2.F Catch
3.Finally
4.Main catch

Теперь уберем из метода Main блок try-catch и снова запустим программу. На этот раз результат будет немного другой, хотя в обоих случаях exception покидает метод F():
1.Try
2.F Catch
3.Информация об ошибке
4.Finally

Заключение


В большинстве случаев, необычное с первого взгляда поведение, оказывается вполне объянимым или уже задокументированным. Но, согласитесь, что мало кто досконально читает help перед тем как писать код. Так что желаю вам пореже встречаться с такими сюрпризами.
Tags:
Hubs:
Total votes 31: ↑16 and ↓15+1
Comments35

Articles