C# ఎన్‌క్యాప్సులేషన్, యాక్సెస్ మోడిఫైయర్స్ & Auto-Properties (get, set, init)

⚡ Modern C# 12 / .NET 8 LTS 📖 Chapter 14 of 20 🏛️ Phase 04: ఆబ్జెక్ట్ ఓరియెంటెడ్ ప్రోగ్రామింగ్ (OOP) 📅 2026 Academic Edition
📌 Covered in this chapter: డేటా హైడింగ్ తత్వం · 6 యాక్సెస్ మోడిఫైయర్లు (public, private, protected, internal, protected internal, private protected) · Backing Fields & Full Properties · Auto-Implemented Properties { get; set; } · private set & రీడ్-ఓన్లీ డిజైన్ · C# 9+ init-only యాక్సెసర్స్ · ఎక్స్‌ప్రెషన్-బాడీడ్ కంప్యూటెడ్ ప్రాపర్టీస్ (=>) · C# 11 required కీవర్డ్ · సెక్యూర్ పేమెంట్ గేట్‌వే వాలెట్ ప్రాజెక్ట్ · 5 ఇంటరాక్టివ్ క్విజ్ ప్రశ్నలు

OOP మొదటి రక్షణ కవచం: ఎన్‌క్యాప్సులేషన్ (Encapsulation)! 🛡️

ఒక కారు నడిపే డ్రైవర్‌కు ఇంజిన్ లోపల ఉండే పిస్టన్లు, ఫ్యూయల్ ఇంజెక్టర్లు నేరుగా చేతులతో తాకడానికి అందుబాటులో ఉండవు. డ్రైవర్ కేవలం స్టీరింగ్, యాక్సిలరేటర్, బ్రేక్ పెడల్స్ అనే సురక్షితమైన ఇంటర్‌ఫేస్ ద్వారా మాత్రమే కారును నియంత్రిస్తాడు. ఒకవేళ డ్రైవర్ నేరుగా నడుస్తున్న పిస్టన్‌ను తాకగలిగితే ప్రమాదం తప్పదు!

సాఫ్ట్‌వేర్ ఇంజనీరింగ్‌లో కూడా ఇదే నియమం వర్తిస్తుంది. ఒక క్లాస్ లోపల ఉండే సెన్సిటివ్ డేటాను (ఉదా: బ్యాంక్ బ్యాలెన్స్, పాస్‌వర్డ్ హాష్, వాలెట్ క్రెడిట్స్) బయటి కోడ్ నేరుగా మార్చకుండా దాచిపెట్టే పద్ధతినే డేటా హైడింగ్ (Data Hiding) లేదా ఎన్‌క్యాప్సులేషన్ (Encapsulation) అంటారు. C# లోని 6 యాక్సెస్ మోడిఫైయర్లు, మరియు ఆధునిక Properties (get, set, init, required) ద్వారా అత్యున్నత రక్షణ కలిగిన సాఫ్ట్‌వేర్ ఆర్కిటెక్చర్‌ను ఎలా నిర్మించాలో ఈ అధ్యాయంలో సమగ్రంగా నేర్చుకుందాం!

1 🛡️ ఎన్‌క్యాప్సులేషన్ (Encapsulation) అంటే ఏమిటి? పబ్లిక్ ఫీల్డ్స్ ఎందుకు ప్రమాదకరం?

ఎన్‌క్యాప్సులేషన్ (Encapsulation) అంటే ఒక ఆబ్జెక్ట్ యొక్క డేటా (Fields) మరియు ఆ డేటాను మార్చే పద్ధతులను (Methods/Properties) ఒకే ఒక క్యాప్సూల్ లాంటి యూనిట్‌లో బంధించి, అంతర్గత వివరాలను బయటి ప్రపంచం నుండి దాచడం.

మీరు ఒక క్లాస్‌లో ఫీల్డ్స్‌ను public గా డిక్లేర్ చేస్తే ఏం జరుగుతుందో ఈ కింది ఉదాహరణలో చూడండి:

csharp · The Danger of Public Fields
// ❌ అత్యంత ప్రమాదకరమైన బ్యాడ్ కోడ్ (No Encapsulation)
public class UnsafeAccount
{
    public string AccountHolder;
    public decimal Balance; // పబ్లిక్ ఫీల్డ్!
}

UnsafeAccount acc = new UnsafeAccount();
acc.Balance = 10000m;

// ఎవరైనా పొరపాటున లేదా దురుద్దేశంతో బ్యాలెన్స్‌ను రుణాత్మకం చేయవచ్చు!
acc.Balance = -999999m; // 😱 ఎటువంటి అడ్డంకి లేదు! డేటా కరప్ట్ అయిపోయింది!

ఈ తీవ్రమైన లోపాన్ని అరికట్టడానికే ఎన్‌క్యాప్సులేషన్ గోల్డెన్ రూల్: "ఫీల్డ్స్‌ను ఎల్లప్పుడూ private గా ఉంచాలి. వాటిని చదవడానికి లేదా మార్చడానికి పబ్లిక్ మెథడ్స్ లేదా ప్రాపర్టీల ద్వారా మాత్రమే కఠినమైన నిబంధనలతో (Validation Rules) అనుమతించాలి."

2 🔐 C# లోని 6 యాక్సెస్ మోడిఫైయర్లు (The 6 Access Modifiers)

C# ఇతర భాషల కంటే అత్యంత సూక్ష్మమైన యాక్సెస్ కంట్రోల్‌ను అందిస్తుంది. ఇందులో మొత్తం 6 యాక్సెస్ మోడిఫైయర్లు ఉన్నాయి:

మోడిఫైయర్ యాక్సెస్ పరిధి (Scope) ఎక్కడ అందుబాటులో ఉంటుంది?
public అపరిమితం (Unrestricted) ఏ ప్రాజెక్ట్ లేదా ఏ అసెంబ్లీ (.dll) నుండి అయినా యాక్సెస్ చేయవచ్చు.
private అత్యంత కఠినం (Class Only) ఆ క్లాస్ లేదా స్ట్రక్ట్ కర్లీ బ్రేసెస్ { } లోపల మాత్రమే. బయటికి కనిపించదు.
protected వారసత్వం (Inheritance) ఆ క్లాస్ మరియు దాని చైల్డ్ క్లాసుల (Derived Classes) లోపల మాత్రమే.
internal అసెంబ్లీ బౌండరీ (Same Assembly) అదే ప్రాజెక్ట్ / కంపైల్ అయిన అదే .dll లేదా .exe లోపల ఉన్న అన్ని క్లాసులకు కనిపిస్తుంది. బయటి ప్రాజెక్టులకు కనిపించదు.
protected internal యూనియన్ (Protected OR Internal) అదే అసెంబ్లీలో ఎక్కడైనా OR ఇతర అసెంబ్లీలలోని డిరైవ్డ్ క్లాసుల్లో మాత్రమే.
private protected ఇంటర్‌సెక్షన్ (Protected AND Internal) అదే అసెంబ్లీలో ఉంటూ, డిరైవ్డ్ క్లాస్ అయి ఉండాలి (C# 7.2+).
📌 C# డీఫాల్ట్ యాక్సెస్ నియమాలు (Default Modifiers):
• క్లాస్ లెవెల్‌లో (Top-level Class): internal (మీరు ఏమీ రాయకపోతే).
• మెంబర్ లెవెల్‌లో (Fields, Methods in Class): private (మీరు ఏమీ రాయకపోతే).

3 ☕ క్లాసిక్ గెట్టర్స్ & సెట్టర్స్ vs C# ప్రాపర్టీస్

జావా (Java) లేదా C++ లో ఫీల్డ్స్‌ను ఎన్‌క్యాప్సులేట్ చేయడానికి సాంప్రదాయకంగా రెండు పబ్లిక్ మెథడ్స్ రాస్తారు: GetBalance() మరియు SetBalance(decimal value).

csharp · Traditional Java-Style Getters/Setters vs Modern C#
// 1. పాత జావా తరహా పద్ధతి (C# లో ఇది రికమండ్ చేయరు):
public class JavaStyleAccount
{
    private decimal _balance;

    public decimal GetBalance() => _balance;

    public void SetBalance(decimal value)
    {
        if (value >= 0) _balance = value;
    }
}

// కాల్ చేసే విధానం:
JavaStyleAccount a1 = new JavaStyleAccount();
a1.SetBalance(5000m);
Console.WriteLine(a1.GetBalance()); // ఫంక్షన్ కాల్ బ్రాకెట్లు () తప్పనిసరి!

// ----------------------------------------------------
// 2. C# ప్రాపర్టీ శైలి (Natural Field Syntax with Method Safety!):
public class CSharpAccount
{
    private decimal _balance;

    public decimal Balance
    {
        get => _balance;
        set { if (value >= 0) _balance = value; }
    }
}

// కాల్ చేసే విధానం - వేరియబుల్ లాగే సహజంగా ఉంటుంది!
CSharpAccount a2 = new CSharpAccount();
a2.Balance = 5000m; // లోపల set రన్ అవుతుంది!
Console.WriteLine(a2.Balance); // లోపల get రన్ అవుతుంది!

C# ప్రాపర్టీస్ బయటి ప్రపంచానికి సాధారణ వేరియబుల్ లాగా సహజమైన సింటాక్స్‌తో కనిపిస్తాయి, కానీ లోపల మాత్రం మెథడ్ లాగా రక్షణ వలయాన్ని అమలు చేస్తాయి.

4 🏗️ C# ఫుల్ ప్రాపర్టీ అనాటమీ & `value` కీవర్డ్

ఒక పూర్తి స్థాయి ప్రాపర్టీ (Full Property) లో రెండు విభాగాలు ఉంటాయి:

  1. Backing Field: అసలైన డేటాను దాచే ఒక private వేరియబుల్ (సాధారణంగా _camelCase తో రాస్తారు).
  2. Property Declaration: get మరియు set యాక్సెసర్లు (Accessors) కలిగిన పబ్లిక్ ఇంటర్‌ఫేస్.

ఇందులో value అనేది C# అందించే ఒక ప్రత్యేక కాంటెక్స్చువల్ కీవర్డ్ (Contextual Keyword). బయటి నుండి అసైన్ చేసిన డేటా value అనే పేరుతో సెట్టర్ లోపలికి వస్తుంది.

csharp · Full Property with Validation Logic
public class Student
{
    // 1. ప్రైవేట్ బ్యాకింగ్ ఫీల్డ్
    private int _marks;

    // 2. ఫుల్ ప్రాపర్టీ
    public int Marks
    {
        get
        {
            return _marks;
        }
        set
        {
            // కఠినమైన వాలిడేషన్: మార్కులు 0 నుండి 100 మధ్యే ఉండాలి
            if (value < 0 || value > 100)
            {
                throw new ArgumentOutOfRangeException(nameof(value), "మార్కులు 0 మరియు 100 మధ్య మాత్రమే ఉండాలి!");
            }
            _marks = value; // సరైనది అయితేనే ఫీల్డ్‌లో భద్రపరుస్తుంది
        }
    }
}

Student s = new Student();
s.Marks = 85; // ✅ విజయవంతం
Console.WriteLine($"విద్యార్థి మార్కులు: {s.Marks}");

// s.Marks = 150; // ❌ System.ArgumentOutOfRangeException విసురుతుంది!

5 ⚡ ఆటో-ఇంప్లిమెంటెడ్ ప్రాపర్టీస్ (Auto-Implemented Properties `{ get; set; }`)

ప్రతి చిన్న ప్రాపర్టీకి ప్రత్యేకంగా ప్రైవేట్ బ్యాకింగ్ ఫీల్డ్ రాసుకోవడం విసుగ్గా ఉంటుంది. ఎలాంటి ప్రత్యేక వాలిడేషన్ అవసరం లేని సందర్భాల్లో C# Auto-Implemented Properties ను ప్రవేశపెట్టింది.

public string Email { get; set; } = "user@example.com";

మీరు ఈ ఒక్క లైన్ రాయగానే, C# కంపైలర్ IL (Intermediate Language) లో ఒక గుప్తమైన బ్యాకింగ్ ఫీల్డ్‌ను (ఉదా: <Email>k__BackingField) ఆటోమేటిక్‌గా జనరేట్ చేస్తుంది. భవిష్యత్తులో ఎప్పుడైనా దీనికి వాలిడేషన్ లాజిక్ అవసరమైతే, క్లాస్ బయటి కోడ్‌ను మార్చకుండా సులభంగా ఫుల్ ప్రాపర్టీగా మార్చుకోవచ్చు!

6 🔒 రీడ్-ఓన్లీ ప్రాపర్టీస్ & ప్రైవేట్ సెట్టర్స్ (`{ get; private set; }`)

ఒక వేరియబుల్‌ను బయటి ప్రపంచం చదవవచ్చు (Read), కానీ మార్చడానికి (Write) అనుమతి ఉండకూడదు. కేవలం క్లాస్ లోపలి మెథడ్స్ మాత్రమే మార్చగలగాలి. దీనిని సాధించడానికి C# లో యాక్సెసర్-లెవల్ యాక్సెస్ మోడిఫైయర్లు ఉన్నాయి:

csharp · Private Set & Read-Only Properties
public class SecureVault
{
    // 1. బయటికి రీడ్-ఓన్లీ, క్లాస్ లోపల మాత్రమే సెట్ చేయవచ్చు
    public decimal VaultBalance { get; private set; }

    // 2. ప్యూర్ రీడ్-ఓన్లీ (గెట్టర్ మాత్రమే ఉంది - కన్‌స్ట్రక్టర్‌లో తప్ప మారదు)
    public string VaultId { get; }

    public SecureVault(string id, decimal openingFunds)
    {
        VaultId = id;
        VaultBalance = openingFunds;
    }

    public void AddFunds(decimal amount)
    {
        if (amount > 0) VaultBalance += amount;
    }
}

SecureVault vault = new SecureVault("VAULT-007", 500000m);
Console.WriteLine($"వాల్ట్ ID: {vault.VaultId}, నిధులు: ₹{vault.VaultBalance:N2}");

// vault.VaultBalance = 900000m; // ❌ కంపైల్ ఎర్రర్: The set accessor is inaccessible!
vault.AddFunds(25000m); // ✅ సురక్షితమైన మెథడ్ ద్వారా మాత్రమే మార్పు సాధ్యం!

7 💎 `init`-ఓన్లీ యాక్సెసర్స్ (C# 9+ Immutable Properties)

గతంలో { get; } లేదా { get; private set; } వాడినప్పుడు ఒక సమస్య ఉండేది: ఆబ్జెక్ట్ ఇనిషియలైజర్ సింటాక్స్ new User { Id = 101 } పనిచేసేది కాదు. కేవలం కన్‌స్ట్రక్టర్ పారామీటర్ ద్వారానే ఇవ్వాల్సి వచ్చేది.

ఈ సమస్యకు అద్భుతమైన ఆధునిక పరిష్కారమే C# 9 లో వచ్చిన init యాక్సెసర్!

  • ఆబ్జెక్ట్ పుట్టేప్పుడు (Instantiation / Object Initializer): విలువను ఉచితంగా సెట్ చేయవచ్చు.
  • ఆబ్జెక్ట్ క్రియేట్ అయిన మరుక్షణమే: అది శాశ్వతంగా రీడ్-ఓన్లీ (Immutable) గా మారిపోతుంది! ఆ తర్వాత ఎవరూ దాన్ని మార్చలేరు.
csharp · init Accessor for Immutability
public class CitizenRecord
{
    // జీవితంలో ఒక్కసారే సెట్ చేయగల ఆధార్ మరియు పాన్ నంబర్లు
    public string AadhaarNumber { get; init; }
    public string PanCard { get; init; }

    // ఇది ఎప్పుడైనా మారవచ్చు
    public string ResidentialAddress { get; set; }
}

// 1. ఆబ్జెక్ట్ ఇనిషియలైజర్ లో init ప్రాపర్టీలకు విలువ ఇవ్వవచ్చు!
CitizenRecord citizen = new CitizenRecord
{
    AadhaarNumber = "9988-7766-5544",
    PanCard = "ABCDE1234F",
    ResidentialAddress = "హైదరాబాద్, తెలంగాణ"
};

// 2. అడ్రస్ మార్చవచ్చు
citizen.ResidentialAddress = "విశాఖపట్నం, ఆంధ్రప్రదేశ్"; // ✅ OK

// 3. ఆధార్ మార్చడానికి ప్రయత్నిస్తే?
// citizen.AadhaarNumber = "1122-3344-5566"; // ❌ కంపైలర్ ఎర్రర్: Init-only property can only be assigned in an object initializer!

8 🧮 ఎక్స్‌ప్రెషన్-బాడీడ్ కంప్యూటెడ్ ప్రాపర్టీస్ (Computed Properties `=>`)

కొన్ని ప్రాపర్టీలు మెమరీలో డేటాను నిల్వ చేసుకోవు. ఇతర ప్రాపర్టీల ఆధారంగా ఎప్పటికప్పుడు అప్పటికప్పుడు లెక్కించి ఫలితాన్ని ఇస్తాయి. వీటిని కంప్యూటెడ్ లేదా కాలిక్యులేటెడ్ ప్రాపర్టీస్ (Computed Properties) అంటారు.

C# లో ఫ్యాట్-యారో (=>) సింటాక్స్ ఉపయోగించి ఒకే లైన్‌లో వీటిని ఎలిగెంట్‌గా రాయవచ్చు:

csharp · Computed Expression-Bodied Properties
public class OrderItem
{
    public string ItemName { get; set; }
    public decimal UnitPrice { get; set; }
    public int Quantity { get; set; }
    public decimal TaxRatePercentage { get; set; } = 18.0m; // 18% GST

    // కంప్యూటెడ్ ప్రాపర్టీ 1: సబ్‌టోటల్
    public decimal SubTotal => UnitPrice * Quantity;

    // కంప్యూటెడ్ ప్రాపర్టీ 2: ట్యాక్స్ మొత్తం
    public decimal TaxAmount => SubTotal * (TaxRatePercentage / 100m);

    // కంప్యూటెడ్ ప్రాపర్టీ 3: గ్రాండ్ టోటల్
    public decimal GrandTotal => SubTotal + TaxAmount;

    // కంప్యూటెడ్ ప్రాపర్టీ 4: ఫార్మాట్ చేసిన వివరణ
    public string Summary => $"{ItemName} ({Quantity} nos) -> మొత్తం: ₹{GrandTotal:N2}";
}

var item = new OrderItem { ItemName = "మెకానికల్ కీబోర్డ్", UnitPrice = 3500m, Quantity = 2 };
Console.WriteLine(item.Summary);
// అవుట్‌పుట్: మెకానికల్ కీబోర్డ్ (2 nos) -> మొత్తం: ₹8,260.00

9 🚨 C# 11 `required` మోడిఫైయర్ — కంపైల్-టైమ్ ఆబ్జెక్ట్ సేఫ్టీ

గతంలో ఒక ఆబ్జెక్ట్ క్రియేట్ చేసేటప్పుడు డెవలపర్ ఏదైనా ముఖ్యమైన ప్రాపర్టీని (ఉదా: Email) ఇవ్వడం మర్చిపోతే, రన్‌టైమ్‌లో NullReferenceException వచ్చి యాప్ క్రాష్ అయ్యేది. దీనికి ఒకే పరిష్కారం పారామీటరైజ్డ్ కన్‌స్ట్రక్టర్ మాత్రమే ఉండేది.

కానీ C# 11 (.NET 7+) లో వచ్చిన required మోడిఫైయర్ ఆబ్జెక్ట్ ఇనిషియలైజర్లలో కూడా తప్పనిసరి ఫీల్డ్స్‌ను ఎన్‌ఫోర్స్ చేస్తుంది!

csharp · required Modifier in C# 11+
public class UserProfile
{
    // తప్పనిసరిగా ఇవ్వాల్సిన ప్రాపర్టీలు
    public required string Username { get; init; }
    public required string Email { get; init; }

    // ఐచ్ఛికం (Optional)
    public string PhoneNumber { get; set; } = "N/A";
}

// ✅ సరైన వినియోగం: required ప్రాపర్టీలు రెండూ ఇచ్చాం
var u1 = new UserProfile
{
    Username = "vijay_kumar",
    Email = "vijay@company.com"
};

// ❌ కంపైల్ ఎర్రర్: Required member 'UserProfile.Email' must be set in object initializer!
// var u2 = new UserProfile { Username = "anand" };

10 ⚖️ Auto-Properties vs Backing Fields — సమగ్ర పోలిక పట్టిక

ఒక ప్రొఫెషనల్ C# ఆర్కిటెక్ట్‌గా ఎప్పుడు ఆటో-ప్రాపర్టీ వాడాలి? ఎప్పుడు బ్యాకింగ్ ఫీల్డ్ వాడాలి? అనే స్పష్టత ఉండాలి:

ఫీచర్ / అవసరం Auto-Property ({ get; set; }) Full Property (Backing Field తో)
వాలిడేషన్ లాజిక్ వీలుకాదు (No custom logic) ఖచ్చితంగా సాధ్యం (if-else, Exception throwing)
కోడ్ పొడవు (Boilerplate) కేవలం 1 లైన్ మాత్రమే (Clean) ఫీల్డ్ + get + set (కనీసం 8-10 లైన్లు)
డేటాబేస్ / ORM మ్యాపింగ్ Entity Framework Core కు అనుకూలం డోమైన్ డ్రివెన్ డిజైన్ (DDD) రిచ్ ఎంటిటీలకు శ్రేష్టం
ఇన్‌మెమరీ ఫీల్డ్ కంట్రోల్ కంపైలర్ ఆటోమేటిక్ ఫీల్డ్ ఇస్తుంది డెవలపర్‌కు ఫీల్డ్‌పై పూర్తి నియంత్రణ ఉంటుంది
సిఫార్సు 90% సాధారణ DTOs, మోడల్స్‌కు వాడండి బిజినెస్ రూల్స్, బ్యాంకింగ్ బ్యాలెన్స్, ఏజ్ లిమిట్లకు వాడండి

11 💡 బెస్ట్ ప్రాక్టీసెస్ — గెట్టర్లలో సైడ్-ఎఫెక్ట్స్ ఉంచకూడదు!

C# కోడింగ్ ప్రమాణాలలో అత్యంత కీలకమైన ఆర్కిటెక్చరల్ రూల్: "A property getter must be fast and free of side-effects!"

  • ❌ గెట్టర్ లోపల ఫైల్ డౌన్‌లోడ్ లేదా డేటాబేస్ క్వెరీలు పెట్టకూడదు: ప్రాపర్టీని చూసినప్పుడు డెవలపర్ అది మెమరీలో తక్షణమే వస్తుందని భావిస్తారు. నెట్‌వర్క్ కాల్ లేదా భారీ లూప్స్ ఉంటే దాన్ని మెథడ్‌గా (FetchDataAsync()) మార్చాలి.
  • ❌ గెట్టర్ ఆబ్జెక్ట్ స్టేట్‌ను మార్చకూడదు: get { _counter++; return _data; } లాంటివి విచిత్రమైన బగ్స్‌కు దారితీస్తాయి, ఎందుకంటే డీబగ్గర్‌లో మౌస్ ఓవర్ చేసినప్పుడు కూడా గెట్టర్ రన్ అయి కౌంటర్ పెరిగిపోతుంది!
  • ✅ ఎక్సెప్షన్లను కేవలం సెట్టర్లలో మాత్రమే విసరాలి: చెల్లని ఇన్‌పుట్ వచ్చినప్పుడు మాత్రమే సెట్టర్‌లో ఎర్రర్ ఇవ్వాలి.

12 💳 రియల్-వరల్డ్ ప్రాజెక్ట్ — సెక్యూర్ పేమెంట్ గేట్‌వే వాలెట్ సిస్టమ్ (Secure Digital Wallet Engine)

ఈ అధ్యాయంలో నేర్చుకున్న Private fields, Full properties with validation, init, required, మరియు Computed properties అన్నింటినీ అనుసంధానించి ఒక ఎంటర్‌ప్రైజ్ డిజిటల్ పేమెంట్ వాలెట్ ఇంజిన్ (Digital Wallet Engine v1.0) నిర్మిద్దాం.

csharp · Secure Digital Wallet & Payment Engine
using System;
using System.Collections.Generic;

Console.OutputEncoding = System.Text.Encoding.UTF8;

Console.WriteLine("=================================================");
Console.WriteLine("💳 మన పేమెంట్స్ - సెక్యూర్ డిజిటల్ వాలెట్ ఇంజిన్ v1.0");
Console.WriteLine("=================================================\n");

public enum WalletTier { Basic, Gold, Platinum }

public class DigitalWallet
{
    // 1. init-only ప్రాపర్టీస్ (ఒక్కసారి పుట్టాక ఎవరూ మార్చలేరు)
    public string WalletId { get; init; }
    public string KycPan { get; init; }

    // 2. required ప్రాపర్టీ (తప్పనిసరిగా ఇవ్వాలి)
    public required string RegisteredMobile { get; init; }
    public required string AccountHolderName { get; init; }

    // 3. బ్యాకింగ్ ఫీల్డ్ తో ఫుల్ ప్రాపర్టీ (కఠినమైన బ్యాలెన్స్ భద్రత)
    private decimal _balance;
    public decimal Balance
    {
        get => _balance;
        private set
        {
            if (value < 0) throw new InvalidOperationException("వాలెట్ బ్యాలెన్స్ రుణాత్మకం (Negative) కాకూడదు!");
            _balance = value;
        }
    }

    // 4. Auto-property with private set
    public WalletTier Tier { get; private set; } = WalletTier.Basic;
    public bool IsKycVerified => !string.IsNullOrWhiteSpace(KycPan);

    // 5. Computed Property (టైర్ ఆధారంగా రోజువారీ పరిమితి)
    public decimal DailySpendLimit => Tier switch
    {
        WalletTier.Basic => 10000.00m,
        WalletTier.Gold => 50000.00m,
        WalletTier.Platinum => 200000.00m,
        _ => 5000.00m
    };

    private decimal _todaySpent = 0m;
    public decimal RemainingDailyLimit => DailySpendLimit - _todaySpent;

    // కన్‌స్ట్రక్టర్
    public DigitalWallet(string walletId, string kycPan, decimal initialDeposit = 500.00m)
    {
        WalletId = walletId;
        KycPan = kycPan?.ToUpper();
        Balance = initialDeposit;
        AutoUpgradeTier();
    }

    public void AddMoney(decimal amount)
    {
        if (amount <= 0)
        {
            Console.WriteLine("❌ డిపాజిట్ మొత్తం సున్నా కంటే ఎక్కువ ఉండాలి!");
            return;
        }

        Balance += amount;
        AutoUpgradeTier();
        Console.WriteLine($"✅ ₹{amount:N2} జమ అయ్యింది! ప్రస్తుత బ్యాలెన్స్: ₹{Balance:N2}");
    }

    public bool MakePayment(string merchantName, decimal amount)
    {
        Console.WriteLine($"\n🛒 చెల్లింపు అభ్యర్థన: {merchantName} కు ₹{amount:N2}");

        if (amount <= 0)
        {
            Console.WriteLine("❌ చెల్లింపు మొత్తం చెల్లదు!");
            return false;
        }
        if (amount > Balance)
        {
            Console.WriteLine($"❌ బ్యాలెన్స్ సరిపోదు! ప్రస్తుత బ్యాలెన్స్: ₹{Balance:N2}");
            return false;
        }
        if (amount > RemainingDailyLimit)
        {
            Console.WriteLine($"❌ రోజువారీ ఖర్చు పరిమితి దాటిపోయింది! (మిగిలిన పరిమితి: ₹{RemainingDailyLimit:N2})");
            return false;
        }

        Balance -= amount;
        _todaySpent += amount;
        Console.WriteLine($"🎉 చెల్లింపు విజయవంతం! రిఫరెన్స్: TXN-{Guid.NewGuid().ToString().Substring(0, 8).ToUpper()}");
        Console.WriteLine($"💰 మిగిలిన బ్యాలెన్స్: ₹{Balance:N2} | నేటి మిగిలిన పరిమితి: ₹{RemainingDailyLimit:N2}");
        return true;
    }

    private void AutoUpgradeTier()
    {
        if (Balance >= 100000m && IsKycVerified) Tier = WalletTier.Platinum;
        else if (Balance >= 25000m && IsKycVerified) Tier = WalletTier.Gold;
        else Tier = WalletTier.Basic;
    }

    public void DisplayWalletSummary()
    {
        Console.WriteLine($"\n-------------------------------------------------");
        Console.WriteLine($"👤 ఖాతాదారుడు : {AccountHolderName} ({RegisteredMobile})");
        Console.WriteLine($"🆔 వాలెట్ ID   : {WalletId}");
        Console.WriteLine($"📄 KYC స్థితి   : {(IsKycVerified ? "ధృవీకరించబడింది (" + KycPan + ")" : "పెండింగ్")}");
        Console.WriteLine($"⭐ వాలెట్ టైర్ : {Tier}");
        Console.WriteLine($"💵 ప్రస్తుత నిధులు: ₹{Balance:N2}");
        Console.WriteLine($"⏱️ రోజువారీ లిమిట్: ₹{DailySpendLimit:N2} (మిగిలినది: ₹{RemainingDailyLimit:N2})");
        Console.WriteLine($"-------------------------------------------------");
    }
}

// డ్రైవర్ కోడ్: required & init ఫీచర్స్ తో ఆబ్జెక్ట్ నిర్మాణం
var wallet = new DigitalWallet("WAL-9082", "ABCDE9876K", 30000.00m)
{
    AccountHolderName = "సురేష్ కొణిదెల",
    RegisteredMobile = "+91 98765 43210"
};

wallet.DisplayWalletSummary();

// లావాదేవీల పరీక్ష
wallet.MakePayment("స్మార్ట్ ఎలక్ట్రానిక్స్", 12500.00m);
wallet.MakePayment("సూపర్‌మార్కెట్", 3000.00m);
wallet.AddMoney(50000.00m);

wallet.DisplayWalletSummary();
Console.WriteLine("=================================================");

💻 ఈ వాలెట్ కోడ్‌ను ఆన్‌లైన్ C# కంపైలర్‌లో రన్ చేయండి!

Encapsulation, init, required, Computed Properties మరియు Tier Auto-upgrade లాజిక్‌ను నేరుగా పరిశీలించండి.

13 🎓 ఇంటర్వ్యూ ప్రశ్నలు, బెస్ట్ ప్రాక్టీసెస్ & 5 ఇంటరాక్టివ్ క్విజ్ ప్రశ్నలు

టాప్ ఇంటర్వ్యూ ప్రశ్నలు & సమాధానాలు:

Q1: C# లో init యాక్సెసర్‌కి మరియు private set కి తేడా ఏమిటి?

జవాబు: private set ఉన్న ప్రాపర్టీని ఆబ్జెక్ట్ ఇనిషియలైజర్ new Class { Prop = val } ద్వారా బయటి నుండి సెట్ చేయలేము; కేవలం కన్‌స్ట్రక్టర్ లేదా క్లాస్ మెథడ్స్ ద్వారానే సెట్ చేయగలం. కానీ init ప్రాపర్టీని ఆబ్జెక్ట్ ఇనిషియలైజర్‌లో సెట్ చేసుకోవచ్చు, ఆ క్షణం తర్వాత అది శాశ్వతంగా ఇమ్యుటబుల్ (మార్చలేనిది) అయిపోతుంది.

Q2: internal మరియు protected మధ్య ఉన్న సూక్ష్మ వ్యత్యాసం ఏమిటి?

జవాబు: internal అనేది అసెంబ్లీ బౌండరీపై ఆధారపడి ఉంటుంది — అదే అసెంబ్లీలోని ఏ క్లాస్ అయినా యాక్సెస్ చేయవచ్చు. protected అనేది ఇన్‌హెరిటెన్స్ హైరార్కీపై ఆధారపడి ఉంటుంది — ఇతర అసెంబ్లీల్లో ఉన్నప్పటికీ చైల్డ్ క్లాస్ అయితే మాత్రమే యాక్సెస్ లభిస్తుంది.

🧠 మీ నాలెడ్జ్ చెక్ చేసుకోండి — 5 ఇంటరాక్టివ్ క్విజ్ ప్రశ్నలు

❓ ప్రశ్న 1: క్లాస్ లోపల ఒక వేరియబుల్‌కు ఏ యాక్సెస్ మోడిఫైయర్ ఇవ్వకపోతే డీఫాల్ట్‌గా ఏది వర్తిస్తుంది?
సమాధానం: private. C# మెంబర్ వేరియబుల్స్ మరియు మెథడ్స్‌కు డీఫాల్ట్‌గా అత్యంత కఠినమైన private యాక్సెస్ ఇస్తుంది.
❓ ప్రశ్న 2: ప్రాపర్టీ సెట్టర్ లోపల బయటి నుండి వచ్చే విలువను స్వీకరించే కాంటెక్స్చువల్ కీవర్డ్ ఏది?
సమాధానం: value. set { _field = value; } లో value అనేది అసైన్ చేయబడిన కొత్త డేటాను సూచిస్తుంది.
❓ ప్రశ్న 3: public string FullName => $"{First} {Last}"; అనేది మెమరీలో డేటాను భద్రపరుస్తుందా?
సమాధానం: లేదు. ఇది ఒక ఎక్స్‌ప్రెషన్-బాడీడ్ కంప్యూటెడ్ ప్రాపర్టీ. దీనికి ప్రత్యేక మెమరీ ఉండదు; పిలిచిన ప్రతిసారీ అప్పటికప్పుడు డైనమిక్‌గా లెక్కించి స్ట్రింగ్‌ను రిటర్న్ చేస్తుంది.
❓ ప్రశ్న 4: C# 11 లో వచ్చిన required కీవర్డ్ ప్రయోజనం ఏమిటి?
సమాధానం: ఆబ్జెక్ట్ ఇనిషియలైజర్ రాసేటప్పుడు డెవలపర్ ఆ ప్రాపర్టీని తప్పనిసరిగా ఇనిషియలైజ్ చేయాలని కంపైలర్ ఎన్‌ఫోర్స్ చేస్తుంది. ఇవ్వకపోతే కంపైల్-టైమ్ ఎర్రర్ వస్తుంది.
❓ ప్రశ్న 5: ఒక ప్రాపర్టీ యొక్క getter లో భారీ డేటాబేస్ లేదా నెట్‌వర్క్ కాల్స్ ఎందుకు ఉంచకూడదు?
సమాధానం: ప్రాపర్టీస్ ఎల్లప్పుడూ వేగంగా (O(1)) మరియు దుష్ప్రభావాలు (Side-effects) లేకుండా ఉండాలి. డీబగ్గర్‌లో మౌస్ ఓవర్ చేసినప్పుడు కూడా గెట్టర్స్ రన్ అవుతాయి కాబట్టి భారీ కాల్స్ ఉంటే అప్లికేషన్ స్తంభించిపోతుంది. భారీ పనులకు ఎల్లప్పుడూ మెథడ్స్ వాడాలి.
← Previous: 13. క్లాసెస్ & కన్‌స్ట్రక్టర్స్ Next: 15. ఇన్‌హెరిటెన్స్ & పాలిమార్ఫిజం →
OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on .NET 8 SDK / C# 12 runtime · 2026 Academic Edition