Re[3]: ref local vs null
От: _NN_ www.nemerleweb.com
Дата: 29.05.19 04:53
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Sinclair, Вы писали:


S>>Не знаю, зачем такое может понадобиться, но всёж.


V>Для интеропа часто использую.

V>Интероп требует передавать структуры по указателю в некое АПИ, но:
V>- иногда хочется оставить их value-типами;
V>- иногда требуется подать NULL;
V>- раскидывать unmanaged/fixed повсюду не хочется.

Перегрузка с IntPtr или ссылочным типом не решит проблему ?
struct A { public int i;}

[DllImport("a.dll")
static extern void f(ref A a);

[DllImport("a.dll")
static extern void f(IntPtr a);

class Null { private Null() {} public static Null Null = null; }

[DllImport("a.dll")
static extern void f(Null @null);
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 05:49
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Перегрузка с IntPtr или ссылочным типом не решит проблему ?


для банального
int select(int, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const timeval *timeout)

будет комбинаторика из 12 допустимых сочетаний с NULL плюс один без NULL.
Re[5]: ref local vs null
От: Ночной Смотрящий Россия  
Дата: 29.05.19 06:36
Оценка:
Здравствуйте, vdimas, Вы писали:

V>будет комбинаторика из 12 допустимых сочетаний с NULL плюс один без NULL.


Т4 в помощь
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[6]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 06:45
Оценка: +1 :)
Здравствуйте, Ночной Смотрящий, Вы писали:

V>>будет комбинаторика из 12 допустимых сочетаний с NULL плюс один без NULL.

НС>Т4 в помощь

Вот сюда?
Я б уволил без разговоров.
Re[5]: ref local vs null
От: Sharov Россия  
Дата: 29.05.19 09:21
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, _NN_, Вы писали:


_NN>>Перегрузка с IntPtr или ссылочным типом не решит проблему ?


V>для банального

V>
V>int select(int, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const timeval *timeout)
V>

V>будет комбинаторика из 12 допустимых сочетаний с NULL плюс один без NULL.

И в чем проблема? Вероятнотсь перепутать параметры или что? Внимательнее быть в ентих случаях.
Кодом людям нужно помогать!
Re[6]: ref local vs null
От: alexzzzz  
Дата: 29.05.19 10:13
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Внимательнее быть в ентих случаях.


К сожалению, этот универсальный совет универсально не работает, потому что, как верно заметили ещё древние римляне, errare humanum est.
Re[5]: ref local vs null
От: _NN_ www.nemerleweb.com
Дата: 29.05.19 10:40
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, _NN_, Вы писали:


_NN>>Перегрузка с IntPtr или ссылочным типом не решит проблему ?


V>для банального

V>
V>int select(int, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const timeval *timeout)
V>

V>будет комбинаторика из 12 допустимых сочетаний с NULL плюс один без NULL.
Теперь всё ясно.

Ждём пока наконец Nullable сможем маршалить и тогда проблема решится.
https://github.com/dotnet/coreclr/issues/1297


Как ещё вариант можно использовать указатели, не так типобезопасно выходит но тоже вариант:
public struct HWND { }

[DllImport("user32.dll", CharSet = CharSet.Auto)]
unsafe public static extern int MessageBox(HWND* hWnd, String text, String caption, int options);
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 10:52
Оценка:
Здравствуйте, Sharov, Вы писали:

V>>int select(int, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const timeval *timeout)

V>>будет комбинаторика из 12 допустимых сочетаний с NULL плюс один без NULL.
S>И в чем проблема?

В очевидной упоротости, при наличии простого как 3 копейки альтернативного решения.
Re[6]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 11:42
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Ждём пока наконец Nullable сможем маршалить и тогда проблема решится.

_NN>https://github.com/dotnet/coreclr/issues/1297

Вроде бы в будущем C# 8.0 решили уже — через ref ?.

Т.е. обычные ссылки строго ненуллабельные, а с вопросиком нуллабельные.
Ну и чудесно, как по мне.

Тем более, что в отличие от C++, ref-переменные в C# имеют семантику не ссылок, а именно указателей, бо в С++ ссылка — это алиас, а в C# — значение, т.е. которое запросто можно перезаписать. И семантика управляемого указателя на value-type всё-равно была нужна, вот как раз эта семантика будет обладать полнотой, коль NULL будет валидным значением для nullable-ссылок.
Re[7]: ref local vs null
От: _NN_ www.nemerleweb.com
Дата: 29.05.19 12:37
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Тем более, что в отличие от C++, ref-переменные в C# имеют семантику не ссылок, а именно указателей, бо в С++ ссылка — это алиас, а в C# — значение, т.е. которое запросто можно перезаписать. И семантика управляемого указателя на value-type всё-равно была нужна, вот как раз эта семантика будет обладать полнотой, коль NULL будет валидным значением для nullable-ссылок.


В обычном коде да, но мы про P/Invoke.
Код компилируется, но не работает.
Передать Nullable на данный момент нет возможности из-за ограничения на обобщённый тип:
public struct HWND { IntPtr hwnd; }

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MessageBox(HWND? hWnd, String text, String caption, int options);

static void Main(string[] args)
{
  MessageBox(null, null, null, 0);
}


Unhandled Exception: System.Runtime.InteropServices.MarshalDirectiveException: Cannot marshal 'parameter #1': Generic types cannot be marshaled.

http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[8]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 12:59
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Код компилируется, но не работает.

_NN>Передать Nullable на данный момент нет возможности из-за ограничения на обобщённый тип:

Это C# 8.0?
Насколько я понял, для GC-типов '?' будет директивой компилятору, а не заворачивание в struct Nullable<T> where T : struct.
Re[7]: ref local vs null
От: alexzzzz  
Дата: 29.05.19 13:11
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Тем более, что в отличие от C++, ref-переменные в C# имеют семантику не ссылок, а именно указателей, бо в С++ ссылка — это алиас, а в C# — значение, т.е. которое запросто можно перезаписать.


Не вижу принципиального различия в этом описании. Вообще не вижу особых отличий между ссылками в C++ и ref-ссылками в C#. Для меня то и другое ― алиас. Если для указателя любое значение нормально, оно может меняться во времени (арифметика указателей), а null — естественное значение по умолчанию, то ссылка, если уж возникла, должна указывать на что-то реально существующее. Ссылка на null — мне это дико что в C++, что в C#.
Отредактировано 29.05.2019 13:42 alexzzzz . Предыдущая версия . Еще …
Отредактировано 29.05.2019 13:32 alexzzzz . Предыдущая версия .
Re[9]: ref local vs null
От: _NN_ www.nemerleweb.com
Дата: 29.05.19 14:25
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, _NN_, Вы писали:


_NN>>Код компилируется, но не работает.

_NN>>Передать Nullable на данный момент нет возможности из-за ограничения на обобщённый тип:

V>Это C# 8.0?

Да. В C# 7.3 это не соберётся

V>Насколько я понял, для GC-типов '?' будет директивой компилятору, а не заворачивание в struct Nullable<T> where T : struct.

Тут 'HWND?' означает Nulalble<HWND> потому как struct HWND.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[8]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 14:45
Оценка:
Здравствуйте, alexzzzz, Вы писали:

V>>Тем более, что в отличие от C++, ref-переменные в C# имеют семантику не ссылок, а именно указателей, бо в С++ ссылка — это алиас, а в C# — значение, т.е. которое запросто можно перезаписать.


A>Не вижу принципиального различия в этом описании. Вообще не вижу особых отличий между ссылками в C++ и ref-ссылками в C#. Для меня то и другое ― алиас. Если для указателя любое значение нормально, оно может меняться во времени (арифметика указателей), а null — естественное значение по умолчанию, то ссылка, если уж возникла, должна указывать на что-то реально существующее. Ссылка на null — мне это дико что в C++, что в C#.


Ну вот сам себе и ответил.
Значение ссылки в C# можно изменять.
И для них есть адресная арифметика.

Похоже, тебя смущает одноимённость именований разных сущностей в разных языках.
Re[10]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 14:53
Оценка:
Здравствуйте, _NN_, Вы писали:

V>>Насколько я понял, для GC-типов '?' будет директивой компилятору, а не заворачивание в struct Nullable<T> where T : struct.

_NN>Тут 'HWND?' означает Nulalble<HWND> потому как struct HWND.

О чём и речь, т.е. пример неудачный или неудачный пример его использования.
Чтобы в твоём примере подать NULL в Interop, достаточно сделать так:
MessageBox(default, "blah-blah"...


ref-ссылки на value-type имеет смысл только когда передаются указатели на составные типы данных (структуры), хендлы к таковым не относится.
Re[11]: ref local vs null
От: _NN_ www.nemerleweb.com
Дата: 29.05.19 15:21
Оценка:
Здравствуйте, vdimas, Вы писали:

V>О чём и речь, т.е. пример неудачный или неудачный пример его использования.

Ну HWND это понятно для примера, пусть будет struct MyStructure.

V>Чтобы в твоём примере подать NULL в Interop, достаточно сделать так:

V>
V>MessageBox(default, "blah-blah"...
V>

Это компилируется но падает с той же ошибкой, передать Nullable<> нельзя.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[12]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 15:40
Оценка:
Здравствуйте, _NN_, Вы писали:

V>>Чтобы в твоём примере подать NULL в Interop, достаточно сделать так:

V>>MessageBox(default, "blah-blah"...
_NN>Это компилируется но падает с той же ошибкой, передать Nullable<> нельзя.

Ес-но. ))
Имелось ввиду:
public struct HWND { IntPtr hwnd; }

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int MessageBox(HWND hWnd, string text, string caption, int options);

static void Main(string[] args)
{
  MessageBox(default, "World!!!", "Hello", 0);
}


Только что проверил — работает на ура в C# 7.3.
Re[13]: ref local vs null
От: _NN_ www.nemerleweb.com
Дата: 29.05.19 15:47
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Только что проверил — работает на ура в C# 7.3.


Ну так это совершенно другой пример и работает по другой причине
default(HWND) в памяти представлен нулями и трактуя это как указатель получаем нулевой указатель.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[14]: ref local vs null
От: vdimas Россия  
Дата: 29.05.19 16:30
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>default(HWND) в памяти представлен нулями и трактуя это как указатель получаем нулевой указатель.


ес-но
Re[9]: ref local vs null
От: alexzzzz  
Дата: 29.05.19 17:43
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Ну вот сам себе и ответил.

V>Значение ссылки в C# можно изменять.
V>И для них есть адресная арифметика.

V>Похоже, тебя смущает одноимённость именований разных сущностей в разных языках.

Может, это ты про что-то другое?

В C# переменные могут быть трёх типов: value-, reference- и указатели. По умолчанию передаются/копируются/присваиваются по значению, но при помощи ключевого слова ref можно получать ссылки на эти переменные. Речь про эти ref-ссылки. Какая же у них адресная арифметика?

int a = 100;
int[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

ref int r = ref a;
r++;

r = ref b[5];
r++;

r — это алиас сначала для a, потом для b[5]. Все манипуляции с r будут происходить с a и b[5]. Максимум что можно сделать с самой ссылкой, перенаправить её в новое место, явно указав, куда именно; а не как с указателями, где можно прибавить к адресу левое число — авось куда-нибудь да попадём.

Указатель подразумевает, что есть непревырвая последовательность ячеек памяти, которые можно последовательно или произвольно читать и писать. Указатель может смотреть на любую ячейку. Лежат ли в ней полезные данные, какой-то мусор или access violation — не его забота. Аналогия указателя — индекс в массиве. Знаешь индекс элемента — можешь обращаться к нему, к соседям, вылезти за пределы массива тоже можешь.

Ссылка же указывает на какую-то конкретную ячейку памяти, в которой гарантированно хранится что-то полезное. Существование других ячеек не подразумевается. Адресной арифметики нет. Ссылка не обязана быть адресом — это деталь реализации. Аналогия ссылки — ключ в словаре. Знаешь ключ — имеешь доступ только к соответствующему значению и всё.

Поэтому null-ссылка, которая никуда не указывает, на первый взгляд кажется бредом. Хотя технически возможна и в C# и в С++.
Отредактировано 29.05.2019 18:26 alexzzzz . Предыдущая версия . Еще …
Отредактировано 29.05.2019 18:25 alexzzzz . Предыдущая версия .
Отредактировано 29.05.2019 17:54 alexzzzz . Предыдущая версия .
Отредактировано 29.05.2019 17:52 alexzzzz . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.