[Этюд] new и null
От: QrystaL Украина  
Дата: 12.01.11 15:11
Оценка: 26 (5)
static void NewAndNull<T>()
    where T : new()
{
    T inst = new T();
    if (inst == null)
    {
        // Как сюда попасть?
    }
}


Мне известно 2 способа
Re: [Этюд] new и null
От: perekrestov Украина  
Дата: 12.01.11 15:38
Оценка: 8 (2)
Здравствуйте, QrystaL, Вы писали:

NewAndNull<int?>();
Re[2]: [Этюд] new и null
От: QrystaL Украина  
Дата: 12.01.11 15:41
Оценка:
P>NewAndNull<int?>();

Да, это первый способ
Re: [Этюд] new и null
От: bober_maniac Россия http://bober-maniac.livejournal.com/
Дата: 12.01.11 15:46
Оценка:
Здравствуйте, QrystaL, Вы писали:

QL>
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 (а именно такой получается при использовании конструктора по умолчанию).
Re[2]: [Этюд] new и null
От: Oyster Украина https://github.com/devoyster
Дата: 12.01.11 15:49
Оценка:
Здравствуйте, bober_maniac, Вы писали:

_>Попадет куда угодно, только закажите. Nullable<T> — это только частный случай, у него есть перекрытый operator ==, который выдает true, если HasValue == false (а именно такой получается при использовании конструктора по умолчанию).


А ты попробуй запустить На самом деле не попадёт. Nullable<T> попадает потому, что при его боксинге получается null и сравнение возвращает true.
Re[2]: [Этюд] new и null
От: bober_maniac Россия http://bober-maniac.livejournal.com/
Дата: 12.01.11 15:50
Оценка:
Здравствуйте, 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 — это какой-то класс из сторонней сборки, о котором вы ничего не знаете.
Re[2]: [Этюд] new и null
От: QrystaL Украина  
Дата: 12.01.11 15:53
Оценка:
_>Попадет куда угодно, только закажите. Nullable<T> — это только частный случай, у него есть перекрытый operator ==, который выдает true

Ок, немного уточним

static void NewNull<T>()
    where T : new()
{
    T inst = new T();
    if (Object.ReferenceEquals(inst, null))
    {
        // Можно ли сюда попасть?
    }
}
Re[3]: [Этюд] new и null
От: bober_maniac Россия http://bober-maniac.livejournal.com/
Дата: 12.01.11 15:54
Оценка:
Здравствуйте, 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).
Re: [Этюд] new и null
От: Oyster Украина https://github.com/devoyster
Дата: 12.01.11 15:56
Оценка:
Здравствуйте, QrystaL, Вы писали:

QL>Мне известно 2 способа


Второй способ — сделать так, чтобы для типа Activator.CreateInstance() вернул null (потому что этот вызов компилятор вставит на месте new T()). Наверное, надо копать в сторону MarshalByRefObject или чего-то такого, связанного с проксями.
Re[4]: [Этюд] new и null
От: Oyster Украина https://github.com/devoyster
Дата: 12.01.11 15:58
Оценка:
Здравствуйте, bober_maniac, Вы писали:

_>Судя по всему, при компиляции генерика используется operator == (object, object).


Нет, используется просто сравнение по ссылке. ПОведение такое же, как у Object.ReferenceEquals().
Re[3]: [Этюд] new и null
От: bober_maniac Россия http://bober-maniac.livejournal.com/
Дата: 12.01.11 16:14
Оценка:
Здравствуйте, 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.

Это жжж неспроста.
Re[4]: [Этюд] new и null
От: bober_maniac Россия http://bober-maniac.livejournal.com/
Дата: 12.01.11 16:17
Оценка:
Здравствуйте, bober_maniac, Вы писали:

_>Тут уже я начинаю тупить, потому что

_>1. Судя по рефлектору, у Nullable<T> нет дефолтного конструктора.
_>2. Вызов дефолтного конструктора от Nullable<T> (которого нет) возвращает null.
_>3. Конструкция null.HasValue от Nullable<T> возвращает false вместо NullReferenceException.

_>Это жжж неспроста.


Хотя, у того же Int32 тоже нет reflector-visible конструктора, а тем не менее.
Re[4]: [Этюд] new и null
От: Oyster Украина https://github.com/devoyster
Дата: 12.01.11 16:18
Оценка: +1
Здравствуйте, 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.
Re: [Этюд] new и null
От: Oyster Украина https://github.com/devoyster
Дата: 12.01.11 16:23
Оценка:
Здравствуйте, 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 или чего-то такого, связанного с проксями.


А эксепшн в кнструктре ?
Re[3]: [Этюд] new и null
От: Oyster Украина https://github.com/devoyster
Дата: 12.01.11 16:26
Оценка:
Здравствуйте, Аноним, Вы писали:

А>А эксепшн в кнструктре ?


Ну выбросится exception из метода, код никогда не дойдёт до указанного места. Неужели лень проверить?
Re: [Этюд] new и null
От: desco США http://v2matveev.blogspot.com
Дата: 12.01.11 17:49
Оценка: 12 (2)
Здравствуйте, QrystaL, Вы писали:

QL>
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 способа


один уже назвали, второй наверное такой

    [CBOProxy]
    class CBO : ContextBoundObject {}
    class CBOProxy : ProxyAttribute
    {
        public override MarshalByRefObject CreateInstance(Type serverType)
        {
            return null;
        }
    }
    NewOrNull<CBO>();
Re[2]: [Этюд] new и null
От: QrystaL Украина  
Дата: 12.01.11 17:59
Оценка:
D>один уже назвали, второй наверное такой

D>
D>    [CBOProxy]
D>    class CBO : ContextBoundObject {}
D>    class CBOProxy : ProxyAttribute
D>    {
D>        public override MarshalByRefObject CreateInstance(Type serverType)
D>        {
D>            return null;
D>        }
D>    }
D>    NewOrNull<CBO>();

D>


Да, все верно =)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.