Как напрямую вызвать метод с параметром ref, используя параметр - PullRequest
0 голосов
/ 05 декабря 2018

Я использую метод из устаревшей библиотеки: F (ref T t) where T: struct.Он объявлен как ref только из соображений производительности и не изменяет данные, которые он получает.Эта библиотека не может быть изменена.

В моем коде у меня есть новый метод G (in T t) where T: struct, который вызывает F.

Есть ли способ вызвать F напрямую с полученной ссылкойне копируя его во временное хранилище?

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Да, есть способ (но он использует небезопасную черную магию).

Сначала отказ от ответственности.

Тот факт, что метод F не изменяет structэто только твоя "конвенция".Для компилятора C # struct, предоставляемый ref, является полностью изменяемым.

Наличие struct, предоставленного readonly ref через in, говорит компилятору: пожалуйста, убедитесь, что этот struct не можетбыть мутированным.

Кстати, если вы передаете struct как in, вы должны убедиться, что этот struct объявлен как readonly struct.В противном случае компилятор создаст защитные копии struct (подробнее см. здесь .) Это вторая причина, по которой вы обычно не можете передать ссылку readonly struct на методпринимая struct на ref и изменяя его.

Если вы все еще хотите обойти все эти ограничения, вы можете использовать System.Runtime.CompilerServices.Unsafe NuGet пакет.

В статическом классе Unsafe есть метод, который может вам помочь:

public static ref T AsRef<T>(in T source);

Вот пример:

void F<T>(ref T t) where T : struct
{
}

void G<T>(in T t) where T : struct
{
    F(ref System.Runtime.CompilerServices.Unsafe.AsRef(in t));
}
0 голосов
/ 05 декабря 2018

Я только что прочитал "в".По-видимому, оба, ref и out являются формой вызова по ссылке.Однако основным отличием является «их заявление о намерениях».

in аргументы не могут быть изменены.Они приведены только для справки в целях эффективности, если таковые имеются.

ref аргументы могут или не могут быть изменены.Это наиболее близкий к классическому «звонок по ссылке».На самом деле это единственный способ, который вы получили, когда реализуете его через голые указатели

out аргументы имеют для изменения;это может быть актуально, если значение требует инициализации (например, только для чтения в конструкторе) - если оно передается как переменная out, компилятор может быть уверен, что будет установлен.Компилятор других функций убедился в этом.

В некотором смысле in является своего рода "ref, но readonly".Невозможность назначить что-то, что вы получили как «in», на «ref» или «out», а также заблокировать вас от случайного изменения значения.Я полагаю, вы не сможете обойтись ни с использованием ссылки там (которая делает это возможно бессмысленной), ни с копированием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...