Есть ли способ создать неизменяемый тип записи, поддерживающий инициализацию объекта @{}?C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Есть ли способ создать неизменяемый тип записи, поддерживающий инициализацию объекта @{}?

Сообщение Anonymous »

Следующий код создает тип записи C#, создает его экземпляр с использованием идиомы инициализации объекта хеш-таблицы, а затем изменяет поле записи:
Add-Type -TypeDefinition @'
namespace n {
public record r {
public string s {get; init;}
}
}
'@

$r = [n.r]@{s='value'}
$r
$r.s = 'new_value'
$r

Поле s после инициализации якобы доступно только для чтения, однако вывод выглядит следующим образом:
s
-
value
new_value

Соответствующий C#
using System;

namespace n {
public record r {
public string s {get; init;}
}
}
public class Program
{
public static void Main()
{
var r = new n.r {s="value"};
r.s = "new_value";
}
}

действительно обеспечивает неизменность во время компиляции с ошибкой
Compilation error (line 13, col 3): Init-only property or indexer 'r.s' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.

Я ищу способ создать тип со следующими функциями:
  • свойства доступны только для чтения после инициализация
  • объекты могут быть созданы с использованием краткого именованного синтаксиса инициализации (например, [n.r]@{s='value'} или аналогичного)< /li>
    это обычный .Net тип, естественно понятный компилятору C#
  • может быть скомпилирован в сборку, а затем передан в Add-Type -ReferenceAssemblies
Можно ли создать такой тип?
Типы, которые не работают
Приведенный ниже код пытается сделать это с помощью во всех смыслах я мог придумать такой неизменяемый тип записи на C#. (Я не эксперт по C#, поэтому ожидаю, что, возможно, что-то пропустил.) Для справки, он также пытается сделать то же самое с New-Object -Property. Он выводит следующее:
OK cl init_error init_origi init_mod_error init_after new_error new_origin new_mod_error new_after_
as nal _mod al mod
s
-- -- ---------- ---------- -------------- ---------- --------- ---------- ------------- ----------
X r1 value new_value value new_value
X r2 value new_value value new_value
X r3 value new_value value new_value
X r4 value new_value value new_value
X r5 Cannot create object of type … The property 's' cannot be fo… The value supplied is not val… The property 's' cannot be fo…
X r6 Cannot convert the "System.Co… The property 's' cannot be fo… A constructor was not found. … The property 's' cannot be fo…
X r7 Cannot convert the "System.Co… The property 's' cannot be fo… A constructor was not found. … The property 's' cannot be fo…

Эти методы либо не поддерживают инициализацию объекта хеш-таблицы, либо позволяют изменять свойство объекта после создания.
Add-Type -TypeDefinition @'
namespace n {
public record r1 { public string s {get; init;} }
public record class r2 { public string s {get; init;} }
public record struct r3 { public string s {get; init;} }
public class r4 { public string s {get; init;} }
public class r5 { public string s {get;} }
public class r6 {
public readonly string s;
public r6 (string s) { this.s = s; }
}
public class r7 {
public string s {get;}
public r7 (string s) { this.s = s; }
}
}
'@

$(foreach ($n in 'r1','r2','r3','r4','r5','r6','r7') {
$r = $null
[pscustomobject]@{
class = $n
init_error = $(try { $r = Invoke-Expression "[n.$n]@{s='value'}"}
catch { $_ })
init_original = $r.s
init_mod_error = $(try { $r.s = 'new_value'}
catch { $_ } )
init_after_mod = $r.s
new_error = $(try { $r = New-Object "n.$n" -Property @{s='value'}}
catch {$_})
new_original = $r.s
new_mod_error = $(try { $r.s = 'new_value'}
catch { $_ } )
new_after_mod = $r.s
}
}) |
Select-Object `
-Property @{name='OK';
expression = {if ('value' -in $_.new_after_mod,
$_.init_after_mod ) {'✓'}

else {'X'}}},
* |
Format-Table `
-Property @{e='OK' ; width = 2},
@{e='class' ; width = 2},
@{e='init_error' ; width = 30},
@{e='init_original' ; width = 10},
@{e='init_mod_error' ; width = 30},
@{e='init_after_mod' ; width = 10},
@{e='new_error' ; width = 30},
@{e='new_original' ; width = 10},
@{e='new_mod_error' ; width = 30},
@{e='new_after_mod' ; width = 10}


Подробнее здесь: https://stackoverflow.com/questions/791 ... ject-initi
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»