Cam on @toupswork da mo dau mot cuoc thao luan thu vi ve extension property trong mot bai viet gan day cua toi: Them static getter nho extension. Vi vay, hay cung xem xet hai y tuong kha ky quac de them property vao cac kieu da ton tai bang extension method trong C# 14.
Extension property dua tren ConditionalWeakTable
Hay xem cac binh luan tai day cua @toupswork:
sealed record Person(string Name);
static class PersonExtensions
{
static readonly ConditionalWeakTable<Person, StrongBox<string?>> Nicknames = new();
extension(Person person)
{
public string? Nickname
{
get => Nicknames.TryGetValue(person, out var box) ? box.Value : null;
set => Nicknames.GetOrCreateValue(person).Value = value;
}
}
}
var person = new Person("Robert");
person.Nickname = "Bob";
Chi rieng cach nay da cho phep ban them property vao cac kieu da ton tai ma khong can sua ma nguon cua chung. Vay tai sao lai dung ConditionalWeakTable thay vi Dictionary?
Neu dung Dictionary, vong doi cua dictionary se gan ket voi tat ca cac doi tuong Person duoc luu trong do, va day khong phai dieu chung ta mong muon. Neu dictionary co nhieu muc, no se giu tat ca cac doi tuong do con song ngay ca khi khong con tham chieu nao khac den chung.
ConditionalWeakTable cho phep ta gan du lieu voi mot doi tuong ma khong ngan can doi tuong do duoc bo nho rac thu hoi.
Phan thu hai co the xem la hoi la: StrongBox<T>. Dinh nghia cua no rat don gian:
public class StrongBox<T>
{
public T Value;
public StrongBox(T value) => Value = value;
}
Tai sao can mot lop boc nhu vay? Thong thuong, ta muon phan biet giua mot property chua duoc gan gia tri va mot property da duoc gan gia tri null. Neu luu truc tiep gia tri trong ConditionalWeakTable, ta khong the phan biet hai truong hop nay.
Voi toi, day la mot giai phap rat thanh lich. Tuy nhien, co le toi se khong bao gio dung no trong ma san pham. Du sao thi day van la mot y tuong thu vi de thu nghiem.
Hay lam no phuc tap hon: Tao lop boc
Tat nhien, ta co the tao mot lop boc chua property muon them:
public class PersonWrapper
{
public Person Person { get; }
public string? Nickname { get; set; }
public PersonWrapper(Person person)
{
Person = person;
}
}
Khong. Cach nay qua nha chan, va gan nhu o moi noi ta deu phai dung PersonWrapper thay vi Person. Vi vay, hay lam dung Unsafe va extensions:
// Cung bo cuc field voi Person, voi mot reference field o vi tri dau tien
// Neu Person co bo cuc khac, giai phap nay se gap van de!
sealed class PersonPlus
{
public string Name = "";
public string? Nickname;
public override string ToString() => $"Person {{ Name = {Name} }}";
}
public static class PersonExtensions
{
public static Person Create(string name, string? nickname = null)
=> Unsafe.As<Person>(new PersonPlus { Name = name, Nickname = nickname });
extension(Person person)
{
public string? Nickname
{
get => person is PersonPlus
? Unsafe.As<PersonPlus>(person).Nickname
: null;
set
{
if (person.GetType() != typeof(PersonPlus))
throw new InvalidOperationException(
"This Person was not allocated by PersonExtensions.Create.");
Unsafe.As<PersonPlus>(person).Nickname = value;
}
}
}
}
Person person = PersonExtensions.Create("Steven Giesel");
person.Nickname = "Stevie";
Console.WriteLine(person.Nickname); // "Stevie"
Console.WriteLine(person.Name); // "Steven Giesel"
Y tuong la tao mot doi tuong co cau truc giong doi tuong ban dau, sau do bo sung them property. Tuy nhien, cach nay doi hoi bo cuc field phai trung khop tuyet doi.
Chi can doi ten field, thay doi kieu du lieu hoac thay doi cau truc la giai phap co the hong. Trinh bien dich cung chac chan se canh bao dong person is PersonPlus, vi theo phan tich cua no thi dieu nay khong bao gio co the xay ra. Tuy nhien, trong truong hop nay, dieu do lai co the xay ra.
Hay lam no an toan hon!
De tang them muc do bat chap, ta co the loi dung static constructor de kiem tra bo cuc field:
public static class PersonExtensions
{
static PersonExtensions()
{
// Kiem tra bo cuc
var probe = Create("steven");
if (!ReferenceEquals(probe.Name, "steven"))
throw new InvalidOperationException("Person/PersonPlus layout mismatch.");
}
...
Doan kiem tra nay tao mot doi tuong mau va xac nhan rang field Name dang tro den dung gia tri mong doi. Neu bo cuc cua Person va PersonPlus khong con tuong thich, chuong trinh se nem ra ngoai le ngay khi PersonExtensions duoc khoi tao.
Day la nhung thu thuat rat thu vi de kham pha kha nang cua C# 14, nhung chung khong nen duoc dung trong ma san xuat thong thuong. Giai phap voi ConditionalWeakTable an toan hon nhieu, con cach dung Unsafe phu thuoc manh vao bo cuc noi bo cua doi tuong va co the vo cung mong manh.



