TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 550 subscribers
Post #446 172
در مثال زیر، پیاده‌سازی کامل‌تر Address را می‌بینید که در آن یک متد factory برای ایجاد نمونه‌ها استفاده شده است:
public record Address
{
private Address(
string street,
string city,
string state,
string country,
string zipCode)
{
Street = street;
City = city;
State = state;
Country = country;
ZipCode = zipCode;
}

public string Street { get; init; }
public string City { get; init; }
public string State { get; init; }
public string Country { get; init; }
public string ZipCode { get; init; }

public static Result<Address> Create(
string street,
string city,
string state,
string country,
string zipCode)
{
// بررسی معتبر بودن آدرس

return new Address(street, city, state, country, zipCode);
}
}


🏗 کلاس پایه (Base Class)

روش جایگزین برای پیاده‌سازی Value Objectها، استفاده از یک کلاس پایه به نام ValueObject است.
این کلاس، وظیفهٔ مقایسهٔ ساختاری (structural equality) را از طریق متد انتزاعی GetAtomicValues بر عهده دارد.

کلاس‌های مشتق‌شده از ValueObject باید این متد را پیاده‌سازی کنند و اجزایی را که در مقایسهٔ برابری مؤثر هستند، مشخص نمایند.

✨ مزایای استفاده از کلاس پایه

صراحت (Explicitness): به‌وضوح مشخص است که کدام کلاس‌ها در دامنه (domain) شما نقش Value Object دارند.

کنترل بر اجزای برابری: می‌توانید دقیقاً تعیین کنید چه مقادیری باید در مقایسهٔ برابری در نظر گرفته شوند.

در زیر یک پیاده‌سازی نمونه از کلاس پایهٔ ValueObject را مشاهده می‌کنید که در بسیاری از پروژه‌ها کاربرد دارد:
public abstract class ValueObject : IEquatable<ValueObject>
{
public static bool operator ==(ValueObject? a, ValueObject? b)
{
if (a is null && b is null)
{
return true;
}

if (a is null || b is null)
{
return false;
}

return a.Equals(b);
}

public static bool operator !=(ValueObject? a, ValueObject? b) =>
!(a == b);

public virtual bool Equals(ValueObject? other) =>
other is not null && ValuesAreEqual(other);

public override bool Equals(object? obj) =>
obj is ValueObject valueObject && ValuesAreEqual(valueObject);

public override int GetHashCode() =>
GetAtomicValues().Aggregate(
default(int),
(hashcode, value) =>
HashCode.Combine(hashcode, value.GetHashCode()));

protected abstract IEnumerable<object> GetAtomicValues();

private bool ValuesAreEqual(ValueObject valueObject) =>
GetAtomicValues().SequenceEqual(valueObject.GetAtomicValues());
}


🧩 نمونه پیاده‌سازی Value Object آدرس

در ادامه، Address را به عنوان یک Value Object پیاده‌سازی کرده‌ایم که از ValueObject ارث‌بری می‌کند و متد GetAtomicValues را برای مقایسهٔ اجزای داخلی بازنویسی می‌کند:
public sealed class Address : ValueObject
{
public string Street { get; init; }
public string City { get; init; }
public string State { get; init; }
public string Country { get; init; }
public string ZipCode { get; init; }

protected override IEnumerable<object> GetAtomicValues()
{
yield return Street;
yield return City;
yield return State;
yield return Country;
yield return ZipCode;
}
}
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →