QL>static void NewAndNull<T>()
QL> where T : new()
QL>{
QL> T inst = new T();
QL> if (inst == null)
QL> {
QL> // Как сюда попасть?
QL> }
QL>}
QL>
QL>Мне известно 2 способа
class B
{
public static bool operator ==(B first, B second)
{
return true;
}
public static bool operator !=(B first, B second)
{
return true;
}
}
Попадет куда угодно, только закажите. Nullable<T> — это только частный случай, у него есть перекрытый operator ==, который выдает true, если HasValue == false (а именно такой получается при использовании конструктора по умолчанию).
Здравствуйте, bober_maniac, Вы писали:
_>Попадет куда угодно, только закажите. Nullable<T> — это только частный случай, у него есть перекрытый operator ==, который выдает true, если HasValue == false (а именно такой получается при использовании конструктора по умолчанию).
А ты попробуй запустить На самом деле не попадёт. Nullable<T> попадает потому, что при его боксинге получается null и сравнение возвращает true.
Здравствуйте, bober_maniac, Вы писали:
_>Здравствуйте, QrystaL, Вы писали:
_>Попадет куда угодно, только закажите. Nullable<T> — это только частный случай, у него есть перекрытый operator ==, который выдает true, если HasValue == false (а именно такой получается при использовании конструктора по умолчанию).
А при таком подходе, прощай логика — нарушается закон исключения третьего. Объект, судя по определению, может быть одновременно равен null и не равен null. Единственный способ установить, что же он есть на самом деле — использовать Equals (который тоже можно перекрыть) или ReferenceEquals (который уже перекрыть нельзя).
class B
{
public static bool operator ==(B first, B second)
{
return true;
}
public static bool operator !=(B first, B second)
{
return true;
}
}
[STAThread]
static void Main(string[] args)
{
var b = new B();
var c = b == null && b != null; // true? WTF?
}
А теперь представьте, что B — это какой-то класс из сторонней сборки, о котором вы ничего не знаете.
Здравствуйте, Oyster, Вы писали:
O>Здравствуйте, bober_maniac, Вы писали:
_>>Попадет куда угодно, только закажите. Nullable<T> — это только частный случай, у него есть перекрытый operator ==, который выдает true, если HasValue == false (а именно такой получается при использовании конструктора по умолчанию).
O>А ты попробуй запустить На самом деле не попадёт. Nullable<T> попадает потому, что при его боксинге получается null и сравнение возвращает true.
Да уж, шизофрения.
class B
{
public static bool operator ==(B first, B second)
{
return true;
}
public static bool operator !=(B first, B second)
{
return true;
}
}
static void NewAndNull<T>()
where T : new()
{
T inst = new T();
if (inst == null)
{
Console.WriteLine("Попал");
}
B inst2 = new B();
if (inst2 == null)
{
Console.WriteLine("Попал");
}
}
[STAThread]
static void Main(string[] args)//g
{
NewAndNull<B>();
Console.ReadLine();
}
Выдает "попал" только один раз — на втором входе.
Судя по всему, при компиляции генерика используется operator == (object, object).
Здравствуйте, QrystaL, Вы писали:
QL>Мне известно 2 способа
Второй способ — сделать так, чтобы для типа Activator.CreateInstance() вернул null (потому что этот вызов компилятор вставит на месте new T()). Наверное, надо копать в сторону MarshalByRefObject или чего-то такого, связанного с проксями.
Здравствуйте, QrystaL, Вы писали:
_>>Попадет куда угодно, только закажите. Nullable<T> — это только частный случай, у него есть перекрытый operator ==, который выдает true
QL>Ок, немного уточним
QL>
QL>static void NewNull<T>()
QL> where T : new()
QL>{
QL> T inst = new T();
QL> if (Object.ReferenceEquals(inst, null))
QL> {
QL> // Можно ли сюда попасть?
QL> }
QL>}
QL>
Тут уже я начинаю тупить, потому что
1. Судя по рефлектору, у Nullable<T> нет дефолтного конструктора.
2. Вызов дефолтного конструктора от Nullable<T> (которого нет) возвращает null.
3. Конструкция null.HasValue от Nullable<T> возвращает false вместо NullReferenceException.
Здравствуйте, bober_maniac, Вы писали:
_>Тут уже я начинаю тупить, потому что _>1. Судя по рефлектору, у Nullable<T> нет дефолтного конструктора. _>2. Вызов дефолтного конструктора от Nullable<T> (которого нет) возвращает null. _>3. Конструкция null.HasValue от Nullable<T> возвращает false вместо NullReferenceException.
_>Это жжж неспроста.
Хотя, у того же Int32 тоже нет reflector-visible конструктора, а тем не менее.
Здравствуйте, bober_maniac, Вы писали:
_>1. Судя по рефлектору, у Nullable<T> нет дефолтного конструктора.
Нет, потому что это value type, у них конструкторов по умолчанию и не бывает — вместо этого компилятор использует IL инструкцию initobj.
_>2. Вызов дефолтного конструктора от Nullable<T> (которого нет) возвращает null.
Нет, не так. На самом деле боксинг для Nullable<T> без значения (.HasValue == false) возвращает null.
_>3. Конструкция null.HasValue от Nullable<T> возвращает false вместо NullReferenceException.
Всё верно, потому что для Nullable<T> null — это тоже значение такое. Туда можно записать null, но будет у тебя всё равно значение, потому что value type.
Здравствуйте, QrystaL, Вы писали:
QL>Мне известно 2 способа
Похоже, моё предыдущее предложение неверно наполовину. Я не работал с C# 4.0, но думаю что тут может помочь DynamicObject.TryCreateInstance(), из которого можно вернуть null. К сожалению, не могу проверить код.
Re[2]: [Этюд] new и null
От:
Аноним
Дата:
12.01.11 16:23
Оценка:
Здравствуйте, Oyster, Вы писали:
O>Здравствуйте, QrystaL, Вы писали:
QL>>Мне известно 2 способа
O>Второй способ — сделать так, чтобы для типа Activator.CreateInstance() вернул null (потому что этот вызов компилятор вставит на месте new T()). Наверное, надо копать в сторону MarshalByRefObject или чего-то такого, связанного с проксями.