zequion Ответов: 1

Динамические структуры значения не присваиваются


Я проверял эту проблему в течение многих лет. У меня есть две разные структуры, которые мне нужно передать в качестве параметров в общую функцию. Эти две структуры имеют внутри другую структуру, которая является общей для обеих. Если корень динамический, то значения не присваиваются во внутренней структуре.

В фоновом режиме существует также проблема, что вместо того, чтобы иметь одну структуру ref dynamic, я должен иметь две структуры, потому что вы не можете передать ref struct в ref dynamic или наоборот. Почему?

Внутренние структуры имеют размер, хотя он и не указан в этом коде.

Мне не помогает то, что мне говорят думать по-другому, потому что в общей функции у меня есть много вещей, которые являются общими для обеих структур, и некоторые вещи, которые отличаются.

public struct St_A
{
  public dynamic MyValue1; 
  public string  MyValue2; 

  public struct St_A1     StProp
  public struct St_COMMON StCommon;
}

public struct St_B
{
  public struct St_COMMON StCommon;
}

public struct St_A1
{
  public dynamic MyValue3; 
  public string  MyValue4; 
}

public struct St_COMMON
{
  public int Value;
}

MyFunction()
{
  struct St_A StA = new St_A();
  struct St_B StB = new St_B();
  dynamic MyRet = Function_Common(true, ref StA, ref StB)
}

public static Function_Common(bool Struct_is_A, ref St_A StA, ref St_B StB)
{
  dynamic MyStruct = null;

  if (Struct_is_A)
    MyStruct = (St_A)StA;
  else
    MyStruct = (St_B)StB;

  // This Works.
  MyStruct.MyValue1 = "10";
  MyStruct.MyValue2 = "10";

  // PROBLEM. It does not produce an error and does not assign the value. If from the 
  // debugger I perform the same action, then it is assigned.
  MyStruct.StProp.MyValue3 = "10";
  MyStruct.StProp.MyValue4 = "10";

  // PROBLEM. It does not produce an error and does not assign the value. If from the 
  // debugger I perform the same action, then it is assigned.
  MyStruct.StCommon.Value = 10;
}


Что я уже пробовал:

в Аль-сайтах интернета.в Аль-сайтах интернета.

1 Ответов

Рейтинг:
9

Dave Kreskowiak

Типы структур хранятся в стеке. Проблема с динамикой заключается в том, что невозможно определить размер объекта, который он удерживает, поэтому как далеко код перемещает указатель стека, чтобы один объект или функция возврата не перезаписали часть вашей структуры? Это невозможно.

Вы пытаетесь нарушить почти все пункты, перечисленные в документации ref:

Цитата:
Типы структур Ref
Добавление модификатора ref в объявление структуры определяет, что экземпляры этого типа должны быть распределены стеком. Другими словами, экземпляры этих типов никогда не могут быть созданы в куче как члены другого класса. Основной мотивацией для этой функции был Span<t> и связанные с ним структуры.

Цель сохранения типа структуры ref в качестве переменной, выделенной стеком, вводит несколько правил, которые компилятор применяет для всех типов структур ref.

Вы не можете упаковать структуру ref. Вы не можете назначить тип структуры ref переменной типа object, dynamic или любого другого типа интерфейса.
типы структур ref не могут реализовывать интерфейсы.
Вы не можете объявить структуру ref как член поля класса или обычной структуры. Это включает в себя объявление автоматически реализуемого свойства, которое создает созданное компилятором резервное поле.
Вы не можете объявить локальные переменные, которые являются типами ref struct в асинхронных методах. Вы можете объявить их в синхронных методах, возвращающих типы Task, Task<tresult> или Task-like.
Вы не можете объявить локальные переменные ref struct в итераторах.
Нельзя захватывать переменные структуры ссылки в лямбда-выражения или функции.
Эти ограничения гарантируют, что вы случайно не используете структуру ref таким образом, который мог бы продвинуть ее в управляемую кучу.

Вы можете комбинировать модификаторы, чтобы объявить структуру как readonly ref. Как readonly Реф структура сочетает в себе преимущества и ограничения из структуры ссылки и объявления только для чтения структуры.


[no name]

Где вы нашли эту информацию?

Я вижу огромный список вещей, которые невозможно сделать. Я хочу сделать что-то простое, то есть передать структуру по ссылке динамически, но это не работает. Это техническая проблема C#, которую они не решили.

Теперь у меня есть эта проблема, и я не могу найти другого решения, кроме дублирования сотен строк кода для каждой из структур.

Есть решение?

Dave Kreskowiak

Как я уже сказал в ответе, в документации по ключевому слову ref.

Проблема не является технической в C#. Это технический вопрос о том, как работают стеки, и его невозможно "решить".

Вместо использования структур, которые являются типами значений, хранящихся в стеке, преобразуйте структуры в классы, которые являются ссылочными типами, хранящимися в управляемой куче.

[no name]

Дэйв, у меня есть эта проблема с Sql Server, и никто мне не отвечает. Я работал над чем-то в течение многих лет, и если это не будет решено, моя работа будет бесполезной.

Вы знаете кого-нибудь, кто слышит то, что я объясняю? Спасибо

https://social.msdn.microsoft.com/Forums/en-US/4a17a3fd-5074-4b9b-a05b-0eae7e3f44ae/sql-server-2017-transact-problems-microsoft-does-not-respond-can-you-read?форум=transactsql

Dave Kreskowiak

Нет. Я не имею ни малейшего понятия об этом.

[no name]

Спасибо за вашу помощь, вы нашли документацию в той же ссылке, которую дали мне?

Dave Kreskowiak

Я не давал никаких ссылок, но вот где его можно найти:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref

[no name]

// Что мне действительно нужно, так это вот это:
общественная статический недействительным Function_Common в <Т> (Ссылка Т мысть)
{ ref T MyStruct = ref MySt;

// ОШИБКА КОМПИЛЯТОРА.StProp Не Существует.
MyStruct.StProp.Value1 = "10";
}

ОПЕРАЦИОННАЯ

общественная статический недействительным Function_Common в <Т> (Ссылка Т мысть)
{ // ОШИБКА КОМПИЛЯТОРА.StProp Не Существует.
Мист .StProp.Value1 = "10";
}

/- Еще кое-что я перепробовал.
общественная статический недействительным Function_Common в <Т> (Ссылка Т St_A)
{ // ПРОБЛЕМА. Он не выдает ошибку и не присваивает значение. Если из отладчика я выполняю то же самое действие, то оно назначается.
динамический MyStruct = система.Активатор.CreateInstance<t>();
MyStruct = St_A;

/ Здесь нельзя утверждать, что "содержание структуры неизвестно" и что по этой причине значения не присваиваются.
MyStruct.StProp.Value1 = "10";
}

Dave Kreskowiak

Вы не можете использовать для этого структуру. Преобразуйте его в классы.