Возврат существующего экземпляра из конструктора

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Возврат существующего экземпляра из конструктора

Сообщение Qwertiy » 27.11.2012 (Вт) 23:53

По идее, конструктор должен создавать новый объект, однако, исходя из
Код: Выделить всё
Module All
  Sub Main()
    Console.WriteLine(Object.ReferenceEquals("", New String("a"c, 0)))
    Console.ReadKey()
  End Sub
End Module
делаю вывод, что платформа .NET, скорее всего, поддерживает возможность вернуть нечто другое, уже существующее. Возможно ли подобное реализовать на каком-либо из .NET языков?

PS: Вопрос скорее из любопытства.

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: Возврат существующего экземпляра из конструктора

Сообщение ark » 28.11.2012 (Ср) 9:18

Хм, видимо есть более, а есть менее "существующие сущности" :shock:
Console.WriteLine(Object.ReferenceEquals(Date.MinValue, New Date(0))) - работает

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.11.2012 (Ср) 10:11

С value-типами всегда false. Даже так:
Код: Выделить всё
  Dim X As Integer = 0
  Console.WriteLine(Object.ReferenceEquals(X, X))

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: Возврат существующего экземпляра из конструктора

Сообщение FireFenix » 28.11.2012 (Ср) 17:45

Я наверное слижком глуп, но зачем в конструкторе подменять объект? не проще сразу в логике Obj1 = Obj2?
И какой результат вы ожидали от выше приведённого модуля и Object.ReferenceEquals? По идеологии VB.NET все объекты передаются по ссылке и наверняка эта функця просто развёрнутый аналог "сахара".
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.11.2012 (Ср) 20:12

FireFenix писал(а):Я наверное слижком глуп, но зачем в конструкторе подменять объект?

Я же написал, что вопрос теоретический :)

FireFenix писал(а):И какой результат вы ожидали от выше приведённого модуля и Object.ReferenceEquals?

Что New создаёт новый объект, который не может совпадать с уже существующей пустой строкой. А он совпадает, т. е. New возвращает уже существующий объект. Поэтому и возник вопрос, можно ли такое как-то реализовать :)

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re:

Сообщение Dmitriy2003 » 28.11.2012 (Ср) 20:36

Qwertiy писал(а):С value-типами всегда false. Даже так:
Код: Выделить всё
  Dim X As Integer = 0
  Console.WriteLine(Object.ReferenceEquals(X, X))


MSDN писал(а):Однако обратите внимание, что если objA и objB являются типами значений, они упакованы до того, как они передаются методу ReferenceEquals


Qwertiy писал(а):
Код: Выделить всё
  Console.WriteLine(Object.ReferenceEquals("", New String("a"c, 0)))


Код: Выделить всё
Console.WriteLine(Object.ReferenceEquals(new string('a',0), new string('b',0))); TRUE
Console.WriteLine(Object.ReferenceEquals(new string('a',1), new string('b',1))); FALSE

и это правильно....чего-то другого ожидать?

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.11.2012 (Ср) 20:48

Dmitriy2003 писал(а):и это правильно....чего-то другого ожидать?

Я уже написал чего. Ты понимаешь что такое ReferenceEquals?

Dmitriy2003 писал(а):
Код: Выделить всё
Console.WriteLine(Object.ReferenceEquals(new string('a',0), new string('b',0))); TRUE
Console.WriteLine(Object.ReferenceEquals(new string('a',1), new string('b',1))); FALSE
и это правильно

Console.WriteLine(Object.ReferenceEquals(new string('a',1), new string('a',1))); // False - вот это правильно!

Dmitriy2003 писал(а):MSDN писал(а):

Это был ответ ark'у на пример с Date. И так очевидно.

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re: Возврат существующего экземпляра из конструктора

Сообщение Dmitriy2003 » 28.11.2012 (Ср) 20:52

Qwertiy писал(а):Я уже написал чего. Ты понимаешь что такое ReferenceEquals?

Я то понимаю. А вот судя по твоим постам ты нет
Qwertiy писал(а):Console.WriteLine(Object.ReferenceEquals(new string('a',1), new string('a',1))); // False - вот это правильно!

ну да и тут два разных обьекта и они не равны NULL

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.11.2012 (Ср) 20:56

Dmitriy2003 писал(а):ну да и тут два разных обьекта и они не равны NULL

Какой ещё null? Пустая строка ему не равна. Проверь, если не веришь.

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re:

Сообщение Dmitriy2003 » 28.11.2012 (Ср) 21:12

Qwertiy писал(а):
Dmitriy2003 писал(а):ну да и тут два разных обьекта и они не равны NULL

Какой ещё null? Пустая строка ему не равна. Проверь, если не веришь.

Куда то тебя понесло не в ту сторону.

MSDN писал(а):Object.ReferenceEquals Method
Return Value: true if objA is the same instance as objB or if both are null references; otherwise, false.
String - конструктор (Char, Int32)
Заметки: Если значение параметра count равно нулю, инициализируется экземпляр Empty.
Empty: Представляет пустую строку. Это поле доступно только для чтения.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 28.11.2012 (Ср) 22:23

Dmitriy2003 писал(а):
MSDN писал(а):Заметки: Если значение параметра count равно нулю, инициализируется экземпляр Empty.

Ну так я про это и говорю. New возвращает уже существующий объект, пустую строку, на которую и ссылается String.Empty.

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: Возврат существующего экземпляра из конструктора

Сообщение ark » 29.11.2012 (Чт) 0:36

Qwertiy писал(а):Это был ответ ark'у на пример с Date
Qwertiy писал(а):New возвращает уже существующий объект, пустую строку, на которую и ссылается String.Empty

Вот и я сперва предположил, что если создаваемый объект совпадает с какой-то из имеющихся констант (String.Empty, Date.MinValue и т.п.), то конструктор возвращает именно эту константу. Однако в случае с Date это не так.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 29.11.2012 (Чт) 1:18

ark писал(а):Вот и я сперва предположил, что если создаваемый объект совпадает с какой-то из имеющихся констант (String.Empty, Date.MinValue и т.п.), то конструктор возвращает именно эту константу. Однако в случае с Date это не так.

Во-первых, Date - это value-тип. Во-вторых, String.Empty - это не константа, как и Date.MinValue. А в-третьих, мне не известно других ситуаций, где бы мог возвращаться существующий объект.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 29.11.2012 (Чт) 1:27

Dmitriy2003 писал(а):
MSDN писал(а):Заметки: Если значение параметра count равно нулю, инициализируется экземпляр Empty.

Вот именно, String.Empty, а не ""...
Проверяется так:
Код: Выделить всё
    GetType(String).GetField("Empty", Reflection.BindingFlags.Public Or Reflection.BindingFlags.Static).SetValue(Nothing, "It was an empty string")
    Console.WriteLine(New String("a"c, 0))
    Console.WriteLine(New Text.StringBuilder())
:lol: :mrgreen: :lol:

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: Возврат существующего экземпляра из конструктора

Сообщение ark » 29.11.2012 (Чт) 4:05

Qwertiy писал(а):Во-первых, Date - это value-тип
Хорошо, так устроит?New Date?(Nothing)
Qwertiy писал(а): Во-вторых, String.Empty - это не константа, как и Date.MinValue
Не в терминологии дело. Ну, пусть будут "заранее инициализированные ReadOnly свойства" - что это меняет.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 29.11.2012 (Чт) 6:24

ark писал(а):Хорошо, так устроит? New Date?(Nothing)

Date? - тоже value-тип :)

ark писал(а):Не в терминологии дело. Ну, пусть будут "заранее инициализированные ReadOnly свойства" - что это меняет.

Что это меняет я написал постом выше :D
Да, это не свойство а поле.
А вообще, константы подставляются при компиляции, а значения свойств и полей - при выполнении.

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: Возврат существующего экземпляра из конструктора

Сообщение ark » 29.11.2012 (Чт) 7:21

Qwertiy писал(а):Date? - тоже value
И какой же value у Nothing? :D
Date? - Nullable тип, с помощью которого value превращается в элегантные шорты reference

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 29.11.2012 (Чт) 8:03

ark писал(а):
Qwertiy писал(а):Date? - тоже value
И какой же value у Nothing? :D
Date? - Nullable тип, с помощью которого value превращается в элегантные шорты reference

Ага, конечно :lol: Проверь. И посмотри его декларацию.

Код: Выделить всё
? GetType(Integer?).IsByRef
False
? GetType(Integer?).IsClass
False
? GetType(Integer?).IsMarshalByRef
False
? GetType(Integer?).IsValueType
True

Dmitriy2003
Постоялец
Постоялец
 
Сообщения: 690
Зарегистрирован: 27.05.2003 (Вт) 22:47
Откуда: Deutschland

Re:

Сообщение Dmitriy2003 » 29.11.2012 (Чт) 13:10

Qwertiy писал(а):Вот именно, String.Empty, а не ""...

The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created.

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 29.11.2012 (Чт) 16:03

Dmitriy2003 писал(а):The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created.

Это вообще к чему?

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: Возврат существующего экземпляра из конструктора

Сообщение ark » 01.12.2012 (Сб) 5:26

Qwertiy писал(а):Ага, конечно Проверь. И посмотри его декларацию.
Каюсь, ошибался. Мне казалось, Nullable логичнее сделать классом, а не структурой.
Qwertiy писал(а):Это вообще к чему?
Мне сдаётся, к тому, что String.Empty всегда имеет один и тот же референс. Кстати:
Код: Выделить всё
GetType(String).GetField("Empty", Reflection.BindingFlags.Public Or Reflection.BindingFlags.Static).SetValue(Nothing, "It was an empty string")
Console.WriteLine(Object.ReferenceEquals("", New String("a"c, 0)))
Console.WriteLine(Object.ReferenceEquals(String.Empty, New String("a"c, 0)))
False
True

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 01.12.2012 (Сб) 11:45

ark писал(а):Мне казалось, Nullable логичнее сделать классом, а не структурой.

Аккуратнее с такими фразами... Только generic nullable структура, просто Nullable - класс:
Код: Выделить всё
  Public Sub Main()
    Console.WriteLine(GetType(Nullable).IsClass) ' True
    Console.WriteLine(GetType(Nullable(Of Integer)).IsClass) ' False
    Console.ReadKey()
  End Sub


ark писал(а):Мне сдаётся, к тому, что String.Empty всегда имеет один и тот же референс. Кстати:

Это как раз подтверждает, что конструктор возвращает значение String.Empty, а не константу "".

Код: Выделить всё
  Private Function UseEmpty(ByVal Str As String) As String
    Return If(String.IsNullOrEmpty(Str), String.Empty, Str)
  End Function

  Private Function UseReallyEmpty(ByVal Str As String) As String
    Return If(String.IsNullOrEmpty(Str), "", Str)
  End Function

  Public Sub Main()
    Dim A As String = Nothing

    Console.WriteLine("UseEmpty: {0}", UseEmpty(A))
    Console.WriteLine("UseReallyEmpty: {0}", UseEmpty(A))

    GetType(String).GetField("Empty").SetValue(Nothing, "It was an empty string")

    Console.WriteLine("UseEmpty: {0}", UseEmpty(A))
    Console.WriteLine("UseReallyEmpty: {0}", UseReallyEmpty(A))

    Console.WriteLine(String.IsNullOrEmpty(String.Empty))
    Console.WriteLine(String.IsNullOrEmpty(""))

    Console.ReadKey()
  End Sub
Output:
Код: Выделить всё
UseEmpty:
UseReallyEmpty:
It was an empty stringUseEmpty: It was an empty string
It was an empty stringUseReallyEmpty:
False
True
Обращаю внимание, что Console.WriteLine использует StringBuilder, поэтому значение String.Empty появляется перед выводом. А вот String.IsNullOrEmpty делает правильную проверку - изменённое значение String.Empty пустой строкой не является.

ark
Бывалый
Бывалый
 
Сообщения: 216
Зарегистрирован: 18.07.2011 (Пн) 0:57

Re: Возврат существующего экземпляра из конструктора

Сообщение ark » 03.12.2012 (Пн) 5:17

Qwertiy писал(а):Это как раз подтверждает, что конструктор возвращает значение String.Empty, а не константу "".
http://blogs.msdn.com/b/ericlippert/archive/2009/09/28/string-interning-and-string-empty.aspx
Как следствие:
Код: Выделить всё
GetType(String).GetField("Empty", Reflection.BindingFlags.Public Or Reflection.BindingFlags.Static).SetValue(Nothing, "It was an empty string")
Console.WriteLine(Object.ReferenceEquals("It was an empty string", String.Empty))
Console.WriteLine(Object.ReferenceEquals("It was an empty string", New String("a"c, 0)))
(True,True)


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18

    TopList