C# వేరియబుల్స్, CTS డేటా టైప్స్ (Value vs Reference), var & const

⚡ Modern C# 12 / .NET 8 LTS 🟢 Chapter 02 of 20 📂 Phase 01: C# ఫండమెంటల్స్ & బేసిక్స్ 📅 2026 Academic Edition
📌 Covered in this chapter: మెమరీ కాన్సెప్ట్స్ · CTS (Common Type System) హైరార్కీ · ప్రిమిటివ్ డేటా టైప్స్ మ్యాపింగ్ · Float vs Double vs Decimal ప్రెసిషన్ · Stack (Value Types) vs Heap (Reference Types) · Boxing & Unboxing పెర్ఫార్మెన్స్ · var టైప్ ఇన్ఫరెన్స్ · const vs readonly తేడాలు · default ఆపరేటర్ · Nullable Types (int?) · ఈ-కామర్స్ ఇన్వాయిస్ ప్రాజెక్ట్

హలో C# డెవలపర్! 👋 కంప్యూటర్ మెమరీ ఆర్కిటెక్చర్‌ను శాసించే సమయం వచ్చింది!

ఒక ప్రోగ్రామ్ అంటే కేవలం సూచనల సమాహారం మాత్రమే కాదు—అది డేటాను సేకరించి, విశ్లేషించి, లెక్కించి భద్రపరిచే ఒక జీవ వ్యవస్థ. ఆ డేటాను RAM లో ఎక్కడ దాచాలి, ఎంత స్థలం కేటాయించాలి, మరియు ఏ నిబంధనలతో నిర్వహించాలి అనేది నిర్ణయించే ప్రాథమిక స్తంభాలే వేరియబుల్స్ (Variables) మరియు డేటా టైప్స్ (Data Types).

పైథాన్ లేదా జావాస్క్రిప్ట్ లాంటి డైనమిక్ భాషలతో పోలిస్తే, C# ఒక స్టాటికల్లీ టైప్డ్ & టైప్-సేఫ్ లాంగ్వేజ్. అంటే ప్రతి వేరియబుల్ యొక్క టైప్ కంపైల్ చేసే సమయంలోనే ఖచ్చితంగా తెలిసి ఉండాలి. ఈ అధ్యాయంలో .NET యొక్క CTS (Common Type System), స్టాక్ vs హీప్ మెమరీ మోడల్, బాక్సింగ్/అన్‌బాక్సింగ్ సమస్యలు, ఫైనాన్షియల్ ప్రోగ్రామింగ్‌లో decimal ప్రాముఖ్యత, మరియు var, const, readonly ల మధ్య ఉన్న సూక్ష్మ వ్యత్యాసాలను ప్రాక్టికల్ కోడింగ్‌తో లోతుగా నేర్చుకుందాం!

1 వేరియబుల్ అంటే ఏమిటి? కంప్యూటర్ మెమరీలో డేటా ఎలా స్టోర్ అవుతుంది?

కంప్యూటర్ సైన్స్ పరిభాషలో, వేరియబుల్ (Variable) అనేది కంప్యూటర్ RAM (Random Access Memory) లోని ఒక నిర్దిష్ట స్థానానికి మనం పెట్టుకునే ఒక అర్థవంతమైన పేరు (Named Storage Location). మనం ప్రోగ్రామ్‌లో ఒక వేరియబుల్‌ను డిక్లేర్ చేసినప్పుడు, ఆపరేటింగ్ సిస్టమ్ ఆ డేటా టైప్‌కు సరిపడా బైట్ల మెమరీని రిజర్వ్ చేసి, ఆ చిరునామాను (Memory Address) ఆ వేరియబుల్ పేరుతో అనుసంధానిస్తుంది.

వేరియబుల్ డిక్లరేషన్ & ఇనిషియలైజేషన్ సింటాక్స్:

C# — Variable Declaration Anatomy
// 1. డిక్లరేషన్ (కేవలం మెమరీ రిజర్వ్ చేయడం)
int studentAge;

// 2. అసైన్‌మెంట్ (విలువను నింపడం)
studentAge = 21;

// 3. డిక్లరేషన్ & ఇనిషియలైజేషన్ ఒకేసారి చేయడం (ఉత్తమ పద్ధతి)
int totalMarks = 485;
string studentName = "కార్తీక్ శర్మ";

C# ఐడెంటిఫైయర్ నామకరణ నిబంధనలు (Identifier Rules):

  • వేరియబుల్ పేర్లు కేవలం అక్షరాలు (A-Z, a-z), అంకెలు (0-9), లేదా అండర్‌స్కోర్ (_) తో మాత్రమే ప్రారంభం కావాలి.
  • పేరు మొదటి అక్షరంగా ఎట్టిపరిస్థితుల్లోనూ సంఖ్య (Digit) ఉండకూడదు (ఉదా: 1stRank చెల్లదు, rank1 చెల్లుతుంది).
  • C# రిజర్వ్‌డ్ కీవర్డ్స్‌ను (ఉదా: int, class, for) సాధారణంగా వేరియబుల్ పేర్లుగా వాడలేము. అయితే వాటికి ముందు @ ప్రిఫిక్స్ జోడిస్తే వాడవచ్చు (ఉదా: string @class = "CSE"; — కానీ ఇది రికమండ్ చేయబడదు).
  • C# కేస్-సెన్సిటివ్ (Case-Sensitive): age, Age, మరియు AGE అనేవి మూడు వేర్వేరు వేరియబుల్స్!

2 CTS (Common Type System): .NET యూనివర్సల్ టైప్ హైరార్కీ

.NET ప్లాట్‌ఫారమ్ యొక్క అత్యంత గొప్ప ఆవిష్కరణలలో CTS (Common Type System) ఒకటి. C#, F#, VB.NET వంటి అనేక విభిన్న భాషలు ఒకే రన్‌టైమ్ (CLR) పై ఎలాంటి పొరపాట్లు లేకుండా పరస్పరం మాట్లాడుకోవడానికి CTS ఒక సార్వత్రిక నిబంధనావళిగా పనిచేస్తుంది.

"ప్రతిదీ ఒక ఆబ్జెక్టే" (System.Object):

C# లోని ప్రతి ఒక్క డేటా టైప్—చిన్న సంఖ్య int నుండి మొదలుకొని భారీ క్లాస్ ఆబ్జెక్ట్ వరకు—అన్నీ కూడా System.Object (లేదా దాని అలియాస్ object) అనే ఒకే ఒక్క మాతృమూర్తి (Ultimate Base Type) నుండి ఉద్భవించాయి!

CTS వర్గీకరణ వృక్షం (Type Hierarchy Tree):

System.Object (object)
│
┌────────────────────────────┴────────────────────────────┐
│ │
System.ValueType (Value Types) Reference Types
│ │
┌──────┴──────────────┐ ┌──────────────┴──────────────┐
│ │ │ │ │
Structs / Primitives Enums Classes Arrays Delegates
(int, float, bool, (Custom Enums) (string, (int[], (Action,
char, decimal) Custom Class) string[]) Func)
🎯 రెండు ప్రధాన వర్గాలు:
.NET లోని అన్ని డేటా టైప్స్ కేవలం రెండు పెద్ద సమూహాలుగా విడిపోతాయి:
1. Value Types: డేటా నేరుగా స్టాక్ మెమరీలో నిల్వ అవుతుంది (fast, lightweight).
2. Reference Types: అసలు డేటా హీప్ మెమరీలో ఉండి, దాని చిరునామా (Pointer) మాత్రమే స్టాక్‌లో ఉంటుంది.

3 ప్రిమిటివ్ డేటా టైప్స్: C# కీవర్డ్స్ vs .NET CTS మ్యాపింగ్ పట్టిక

C# లో మనం రాసే int లేదా string అనేవి నిజానికి C# కంపైలర్ అందించిన ముద్దుపేర్లు (Syntactic Aliases)! అంతర్గతంగా ప్రతి C# కీవర్డ్ వెనుక ఒక అధికారిక .NET CTS క్లాస్ ఉంటుంది:

C# కీవర్డ్ .NET CTS క్లాస్ సైజు (Bytes) విలువ పరిధి (Range / Description) డిఫాల్ట్ విలువ
byte System.Byte 1 Byte (8 bits) 0 నుండి 255 (Unsigned) 0
sbyte System.SByte 1 Byte -128 నుండి 127 (Signed) 0
short System.Int16 2 Bytes (16 bits) -32,768 నుండి 32,767 0
int System.Int32 4 Bytes (32 bits) -2,147,483,648 నుండి 2,147,483,647 (~2 Billion) 0
long System.Int64 8 Bytes (64 bits) -9.22 × 1018 నుండి 9.22 × 1018 (భారీ సంఖ్యలు) 0L
float System.Single 4 Bytes ±1.5 × 10−45 నుండి ±3.4 × 1038 (7 దశాంశ అంకెలు) 0.0f
double System.Double 8 Bytes ±5.0 × 10−324 నుండి ±1.7 × 10308 (15-17 దశాంశాలు) 0.0d
decimal System.Decimal 16 Bytes (128 bits) 28-29 ఖచ్చితమైన దశాంశ అంకెలు (ఫైనాన్స్ & కరెన్సీ) 0.0m
bool System.Boolean 1 Byte true లేదా false false
char System.Char 2 Bytes U+0000 నుండి U+FFFF (UTF-16 యూనీకోడ్ అక్షరం) ''
string System.String Heap Size యూనీకోడ్ అక్షరాల శ్రేణి (Reference Type) null

4 Float vs Double vs Decimal: ఫైనాన్షియల్ ప్రోగ్రామింగ్‌లో Decimal ఎందుకు తప్పనిసరి?

దశాంశ సంఖ్యలను (Decimals) నిల్వ చేయడానికి C# మూడు రకాల టైప్స్‌ను అందిస్తుంది: float, double, మరియు decimal. అయితే చాలామంది జూనియర్ డెవలపర్లు చేసే ఘోరమైన తప్పు: బ్యాంకింగ్ లేదా ఈ-కామర్స్ కాలిక్యులేషన్లకు double వాడటం!

బైనరీ ఫ్లోటింగ్ పాయింట్ సమస్య (IEEE 754 Rounding Error):

కంప్యూటర్లు అంతర్గతంగా 2 ఆధారంగా (Base-2 Binary) పనిచేస్తాయి. మనం నిత్యజీవితంలో వాడే 0.1 లేదా 0.2 వంటి దశాంశ భాగాలను బైనరీ రూపంలో ఖచ్చితంగా రిప్రజెంట్ చేయలేము (1/3 ని దశాంశంలో 0.333333... అని అనంతంగా రాసినట్లే). దానివల్ల రౌండింగ్ ఎర్రర్లు వచ్చి పైసలు తేడా వస్తాయి!

లైవ్ డెమో: Double vs Decimal తేడా

C# — Floating Point Precision Trap
using System;

// 1. Double వాడినప్పుడు రౌండింగ్ ఎర్రర్:
double d1 = 0.1;
double d2 = 0.2;
double dSum = d1 + d2;

Console.WriteLine($"Double కూడిక (0.1 + 0.2): {dSum}");
Console.WriteLine($"dSum == 0.3 నా? : {dSum == 0.3}"); // ❌ false వస్తుంది! (0.30000000000000004)

// 2. Decimal వాడినప్పుడు ఖచ్చితమైన సమాధానం:
decimal m1 = 0.1m;
decimal m2 = 0.2m;
decimal mSum = m1 + m2;

Console.WriteLine($"\nDecimal కూడిక (0.1m + 0.2m): {mSum}");
Console.WriteLine($"mSum == 0.3m నా? : {mSum == 0.3m}"); // ✅ true వస్తుంది! (ఖచ్చితంగా 0.3)
🚨 గోల్డెన్ రూల్ (Industry Golden Rule):
పైసలు, రూపాయిలు, డాలర్లు, జీతాలు, ట్యాక్స్‌లు వంటి ద్రవ్య సంబంధిత విలువలన్నింటికీ ఎల్లప్పుడూ decimal (సఫిక్స్ 'm' లేదా 'M') మాత్రమే వాడాలి! గేమింగ్ ఫిజిక్స్, గ్రాఫిక్స్ లేదా సైంటిఫిక్ గణనలకు double వాడవచ్చు ఎందుకంటే అక్కడ కొద్దిపాటి రౌండింగ్ పర్వాలేదు కానీ ప్రాసెసింగ్ వేగం ముఖ్యం.

5 Value Types vs Reference Types: స్టాక్ (Stack) vs హీప్ (Heap) లోతైన ఆర్కిటెక్చర్

C# ఇంటర్వ్యూలలో అడిగే #1 మోస్ట్ ఇంపార్టెంట్ కాన్సెప్ట్: "Value Type మరియు Reference Type మధ్య తేడా ఏమిటి?" వీటి ప్రవర్తనను అర్థం చేసుకోవడానికి కంప్యూటర్ మెమరీ ఆర్కిటెక్చర్ పరిశీలిద్దాం:

ఫీచర్ / అంశం Value Types (స్ట్రక్చర్స్, ప్రిమిటివ్స్) Reference Types (క్లాసెస్, స్ట్రింగ్స్, అర్రేలు)
మెమరీ కేటాయింపు స్థలం వేగవంతమైన Stack మెమరీలో నేరుగా నిల్వ అవుతాయి. డేటా పేలోడ్ Heap లో ఉంటుంది; పాయింటర్ చిరునామా Stack లో ఉంటుంది.
అసైన్‌మెంట్ ప్రవర్తన (Copying) Deep Copy of Value: కొత్త కాపీ తయారవుతుంది. ఒకదానిని మారిస్తే మరొకటి మారదు. Shallow Reference Copy: కేవలం పాయింటర్ మాత్రమే కాపీ అవుతుంది. ఇద్దరూ హీప్‌లోని ఒకే ఆబ్జెక్ట్‌ను సూచిస్తారు!
జీవితకాలం & క్లీనప్ ఫంక్షన్ స్కోప్ ముగియగానే స్టాక్ పాయింటర్ ద్వారా తక్షణమే క్లీన్ అవుతుంది. Garbage Collector (GC) ఎప్పుడు వీలైతే అప్పుడు హీప్ నుండి తొలగిస్తుంది.
ఉదాహరణలు int, float, bool, char, struct, enum string, int[], class, object, delegate

స్టాక్ vs హీప్ మెమరీ విజువల్ డయాగ్రమ్:

[ STACK MEMORY (LIFO) ] [ HEAP MEMORY (Dynamic Pool) ]
┌─────────────────────────────┐ ┌──────────────────────────────┐
│ int x = 10 │ │ │
│ int y = x (y gets value 10) │ │ │
│ │ │ │
│ int[] arr1 ──(0x4000)───────┼─────────────────>│ [ 100, 200, 300 ] @ 0x4000 │
│ │ │ │
│ int[] arr2 ──(0x4000)───────┼──────────────────┘ (ఒకే మెమరీ అడ్రస్‌ను సూచిస్తాయి!)
└─────────────────────────────┘ └──────────────────────────────┘

లైవ్ కోడ్ ప్రూఫ్:

C# — Value Type Copy vs Reference Type Sharing
using System;

// 1. Value Type డెమో:
int a = 50;
int b = a; // a లోని విలువను కాపీ చేసి b కి ఇచ్చాం
b = 999;   // b ని మార్చాం

Console.WriteLine($"a = {a}, b = {b}"); // a మారదు! (a = 50, b = 999)

// 2. Reference Type డెమో (అర్రే):
int[] list1 = new int[] { 10, 20, 30 };
int[] list2 = list1; // కేవలం హీప్ అడ్రస్ మాత్రమే కాపీ అయ్యింది!

list2[0] = 777; // list2 ద్వారా మొదటి ఎలిమెంట్‌ను మార్చాం

// list1[0] కూడా మారిపోతుంది, ఎందుకంటే ఇద్దరూ చూస్తున్నది ఒకే హీప్ బ్లాక్‌ని!
Console.WriteLine($"list1[0] = {list1[0]} (ఆటోమేటిక్‌గా 777 గా మారింది!)");

6 బాక్సింగ్ (Boxing) & అన్‌బాక్సింగ్ (Unboxing): పెర్ఫార్మెన్స్ విశ్లేషణ

C# లోని CTS ప్రకారం Value Types కూడా System.Object నుండి వారసత్వంగా వచ్చాయి. కానీ స్టాక్‌లో ఉండే వాల్యూ టైప్‌ను ఒక రిఫరెన్స్ టైప్ (object) లోకి మార్చాల్సి వచ్చినప్పుడు CLR అంతర్గతంగా చేసే ఆపరేషన్‌ను బాక్సింగ్ (Boxing) అంటారు.

బాక్సింగ్ & అన్‌బాక్సింగ్ డెఫినిషన్స్:

  • బాక్సింగ్ (Boxing): స్టాక్‌లో ఉన్న Value Type ని హీప్‌లో కొత్తగా ఆబ్జెక్ట్ సృష్టించి అందులో ప్యాక్ చేయడం (ఇంప్లిసిట్‌గా జరుగుతుంది).
  • అన్‌బాక్సింగ్ (Unboxing): హీప్‌లో ఉన్న ఆబ్జెక్ట్ బాక్స్ నుండి తిరిగి అసలు Value Type ని బయటకు తీయడం (ఎక్స్‌ప్లిసిట్ కాస్టింగ్ అవసరం).
C# — Boxing & Unboxing Code
using System;

int num = 42; // Value Type on Stack

// 📦 BOXING: num విలువ హీప్‌లో కొత్త ఆబ్జెక్ట్‌గా బాక్స్ అవుతుంది
object boxedObj = num; 

// 📤 UNBOXING: హీప్ ఆబ్జెక్ట్ నుండి తిరిగి స్టాక్ వాల్యూగా మార్చడం
int unboxedNum = (int)boxedObj;

Console.WriteLine($"అసలు విలువ: {num}");
Console.WriteLine($"బాక్స్‌డ్ ఆబ్జెక్ట్: {boxedObj}");
Console.WriteLine($"అన్‌బాక్స్‌డ్ సంఖ్య: {unboxedNum}");
⚡ బాక్సింగ్ వల్ల వచ్చే పెర్ఫార్మెన్స్ సమస్య:
లక్షల సార్లు లూప్‌లో బాక్సింగ్ జరిగితే, ప్రతిసారీ హీప్‌లో మెమరీ కేటాయించబడి Garbage Collector పై విపరీతమైన భారం పడుతుంది. అందుకే పాత C# లోని ArrayList ను పూర్తిగా నిషేధించి, C# 2.0 లో బాక్సింగ్ అవసరం లేని Generics (List<int>) ను పరిచయం చేశారు!

7 var కీవర్డ్ & కంపైల్-టైమ్ టైప్ ఇన్ఫరెన్స్ (Implicit Typing)

C# 3.0 లో మైక్రోసాఫ్ట్ var అనే కీవర్డ్‌ను పరిచయం చేసింది. చాలామంది బిగినర్లు var అంటే జావాస్క్రిప్ట్ లాంటి డైనమిక్ టైప్ అనుకుంటారు. కానీ అది పూర్తిగా తప్పు!

C# లో var అనేది కేవలం కంపైల్-టైమ్ టైప్ ఇన్ఫరెన్స్ (Type Inference). మనం వేరియబుల్‌కు అసైన్ చేసిన కుడివైపు విలువను చూసి, Roslyn కంపైలర్ స్వయంగా సరైన టైప్‌ను స్థిరీకరిస్తుంది. కంపైల్ అయ్యాక IL కోడ్‌లో సాధారణ int లేదా string లాగే స్టోర్ అవుతుంది!

C# — var Usage Rules
using System;

var age = 25;              // కంపైలర్ దీనిని 'int' గా గుర్తిస్తుంది
var salary = 75000.50m;    // కంపైలర్ దీనిని 'decimal' గా గుర్తిస్తుంది
var company = "Google";    // కంపైలర్ దీనిని 'string' గా గుర్తిస్తుంది

// 🚨 ఒకసారి టైప్ నిర్ణయించబడ్డాక వేరే టైప్ విలువను మార్చలేము!
// age = "ఇరవై ఐదు"; // 💥 కంపైల్ ఎర్రర్ CS0029: Cannot implicitly convert type 'string' to 'int'

Console.WriteLine($"age Type: {age.GetType()}");
Console.WriteLine($"salary Type: {salary.GetType()}");
Console.WriteLine($"company Type: {company.GetType()}");

var వాడేటప్పుడు పాటించాల్సిన నిబంధనలు:

  • var x; అని ఒంటరిగా డిక్లేర్ చేయలేము! కుడివైపు తప్పనిసరిగా ఇనిషియలైజ్ చేయాలి.
  • var x = null; రాయలేము, ఎందుకంటే null ఏ టైపో కంపైలర్‌కు అర్థం కాదు.
  • క్లాస్ లెవెల్ ఫీల్డ్స్, మెథడ్ పారామీటర్లు లేదా రిటర్న్ టైప్స్‌గా var వాడలేము; కేవలం లోకల్ వేరియబుల్స్ కోసం మాత్రమే వాడాలి.

8 const vs readonly: కంపైల్-టైమ్ vs రన్‌టైమ్ కాన్‌స్టాంట్స్

ప్రోగ్రామ్‌లో విలువలు ఎప్పటికీ మారకూడదని కోరుకున్నప్పుడు మనం const లేదా readonly వాడతాం. కానీ వీటి మధ్య ఉన్న అంతర్గత తేడా చాలా విలక్షణమైనది:

ఫీచర్ / అంశం const (కంపైల్-టైమ్ కాన్‌స్టాంట్) readonly (రన్‌టైమ్ కాన్‌స్టాంట్)
విలువ కేటాయింపు సమయం కోడ్ రాసేప్పుడే Compile-Time లో స్థిర విలువ ఇవ్వాలి. Run-Time లో (కన్‌స్ట్రక్టర్ ద్వారా) లెక్కించి ఇవ్వవచ్చు.
మెమరీ స్టోరేజ్ IL బైట్‌కోడ్‌లో నేరుగా హార్డ్‌కోడ్ అవుతుంది (మెమరీ స్థలం ఉండదు). హీప్ లేదా ఆబ్జెక్ట్ మెమరీలో ఒక సాధారణ ఫీల్డ్‌లా స్టోర్ అవుతుంది.
స్కోప్ పరిమితి లోకల్ వేరియబుల్స్‌కు మరియు క్లాస్ ఫీల్డ్స్‌కు వాడవచ్చు. కేవలం క్లాస్ లెవెల్ ఫీల్డ్స్‌కు మాత్రమే వర్తిస్తుంది.
వర్షనింగ్ ప్రమాదం వేరే DLL లోని const మారితే, మన ప్రాజెక్ట్‌ను కూడా రీ-కంపైల్ చేయాలి! రీ-కంపైల్ అక్కర్లేదు, రన్‌టైమ్‌లో సరికొత్త విలువను చదువుకుంటుంది.
C# — const vs readonly in a Class
public class BankAccount
{
    // Compile-time: ఎప్పటికీ మారదు
    public const string BankName = "State Bank of India";
    public const double InterestRate = 6.5;

    // Run-time: ఖాతా తెరిచేటప్పుడు యూజర్ డేటాను బట్టి ఒకేసారి నిర్ణయిస్తాం
    public readonly string AccountNumber;
    public readonly DateTime OpeningDate;

    public BankAccount(string accNo)
    {
        AccountNumber = accNo;
        OpeningDate = DateTime.Now; // రన్‌టైమ్ సమయం
        // OpeningDate = DateTime.Now.AddDays(1); // కన్‌స్ట్రక్టర్ తర్వాత ఇక మార్చలేము!
    }
}

9 డిఫాల్ట్ వాల్యూస్ & default ఆపరేటర్

C# లో క్లాస్ లోపల వేరియబుల్స్‌ను డిక్లేర్ చేసి ఎలాంటి విలువ ఇవ్వకపోతే, CLR వాటిని ఆటోమేటిక్‌గా వాటి డిఫాల్ట్ వాల్యూస్ (Default Values) తో సున్నా చేస్తుంది.

ఆధునిక C# లో ఒక డేటా టైప్ యొక్క డిఫాల్ట్ విలువను పొందడానికి default లిటరల్‌ను వాడతాం:

C# — Modern default Operator
using System;

int defaultInt = default;         // 0
bool defaultBool = default;       // false
char defaultChar = default;       // '\0' (null character)
decimal defaultDec = default;     // 0.0m
string? defaultStr = default;     // null

Console.WriteLine($"default int: {defaultInt}");
Console.WriteLine($"default bool: {defaultBool}");
Console.WriteLine($"default decimal: {defaultDec}");
Console.WriteLine($"default string is null? {defaultStr == null}");
🚨 లోకల్ వేరియబుల్స్ మినహాయింపు (CS0165 Alert):
క్లాస్ ఫీల్డ్స్‌కు ఆటోమేటిక్‌గా డిఫాల్ట్ విలువలు వస్తాయి కానీ, ఒక మెథడ్ లోపల రాసే లోకల్ వేరియబుల్స్‌కు ఆటోమేటిక్ డిఫాల్ట్ వాల్యూ రాదు! వాటికి స్పష్టంగా విలువ ఇవ్వకుండా చదవడానికి ప్రయత్నిస్తే కంపైలర్ CS0165: Use of unassigned local variable ఎర్రర్ విసిరి ఆపేస్తుంది.

10 Nullable Value Types: int? మరియు Null-Coalescing (??)

సాధారణంగా int, double, bool వంటి వాల్యూ టైప్స్ ఎల్లప్పుడూ ఏదో ఒక విలువను కలిగి ఉంటాయి, అవి ఎప్పటికీ null కాలేవు. కానీ రియల్ వరల్డ్ SQL డేటాబేస్‌లలో ఒక కాలమ్ లో విలువ లేకపోవచ్చు (ఉదాహరణకు యూజర్ తన వయస్సును లేదా ఫోన్ నంబర్‌ను ఇంకా నమోదు చేయలేదు).

ఇలాంటి సందర్భాల కోసం C# Nullable Value Types ను అందిస్తుంది. టైప్ పక్కన ఒక ప్రశ్నార్థక చిహ్నం (?) పెడితే సరిపోతుంది:

C# — Nullable Value Types & ?? Operator
using System;

// 1. Nullable int డిక్లరేషన్
int? optionalAge = null;

if (optionalAge.HasValue)
{
    Console.WriteLine($"యూజర్ వయస్సు: {optionalAge.Value}");
}
else
{
    Console.WriteLine("యూజర్ వయస్సు ఇంకా నమోదు కాలేదు (null).");
}

// 2. Null-Coalescing ఆపరేటర్ (??) తో సేఫ్ డిఫాల్ట్
// ఒకవేళ optionalAge నల్ అయితే డీఫాల్ట్‌గా 18 తీసుకో:
int finalAge = optionalAge ?? 18;
Console.WriteLine($"ఖరారైన వయస్సు: {finalAge}");

11 ప్రాక్టికల్ ప్రాజెక్ట్: ఈ-కామర్స్ ఆర్డర్ ఇన్వాయిస్ & టాక్స్ కాలిక్యులేటర్

ఇప్పుడు మనం నేర్చుకున్న decimal ఖచ్చితత్వం, వాల్యూ టైప్స్, స్ట్రింగ్స్, const, మరియు స్ట్రింగ్ ఇంటర్‌పోలేషన్ అన్నింటినీ కలిపి ఒక పూర్తి స్థాయి ఈ-కామర్స్ ఇన్వాయిస్ జనరేటర్ (E-Commerce Order Invoice CLI) ను నిర్మిద్దాం:

C# — E-Commerce Order Invoice Generator Project
using System;

// స్థిరమైన నిబంధనలు (Compile-time Constants)
const string StoreName = "మన డిజిటల్ మార్ట్ (Mana Digital Mart)";
const decimal GstRate = 0.18m;      // 18% GST ట్యాక్స్
const decimal DiscountRate = 0.10m; // 10% పండుగ డిస్కౌంట్

// కస్టమర్ & ఆర్డర్ వివరాలు (విభిన్న డేటా టైప్స్ కలయిక)
string customerName = "రాజేష్ కుమార్ పట్నాయక్";
string orderId = "ORD-2026-9874";
DateTime orderDate = DateTime.Now;

// వస్తువుల డేటా (Decimal precision for financial safety)
string itemName = "Logitech MX Master 3S Wireless Mouse";
int quantity = 2;
decimal unitPrice = 8495.00m;

// వ్యాపార గణనలు (Business Logic Calculations)
decimal rawTotal = unitPrice * quantity;
decimal discountAmount = rawTotal * DiscountRate;
decimal taxableAmount = rawTotal - discountAmount;
decimal gstAmount = taxableAmount * GstRate;
decimal grandTotal = taxableAmount + gstAmount;

// ఇన్వాయిస్ ప్రింటింగ్ (Terminal Formatting)
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("==================================================================");
Console.WriteLine($"               🧾 {StoreName}                  ");
Console.WriteLine("==================================================================");
Console.ResetColor();

Console.WriteLine($"ఆర్డర్ ఐడీ    : {orderId}");
Console.WriteLine($"కస్టమర్ పేరు  : {customerName}");
Console.WriteLine($"తేదీ & సమయం  : {orderDate:dd-MMM-yyyy hh:mm tt}");
Console.WriteLine("------------------------------------------------------------------");
Console.WriteLine($"ఐటమ్ పేరు     : {itemName}");
Console.WriteLine($"పరిమాణం       : {quantity} యూనిట్లు");
Console.WriteLine($"యూనిట్ ధర     : ₹{unitPrice:N2}");
Console.WriteLine($"మొత్తం ధర     : ₹{rawTotal:N2}");
Console.WriteLine($"పండుగ రాయితీ  : -₹{discountAmount:N2} (10% OFF)");
Console.WriteLine($"ట్యాక్స్ మొత్తం : +₹{gstAmount:N2} (18% GST)");
Console.WriteLine("------------------------------------------------------------------");

Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"👉 చెల్లించాల్సిన నికర మొత్తం : ₹{grandTotal:N2}");
Console.ResetColor();

Console.WriteLine("==================================================================");
Console.WriteLine("        ధన్యవాదాలు! మీ ఆర్డర్ త్వరలోనే డెలివరీ చేయబడుతుంది.        ");
Console.WriteLine("==================================================================");

🚀 లైవ్ C# కంపైలర్‌లో రన్ చేసి చూడండి!

దశాంశ ఖచ్చితత్వం మరియు కరెన్సీ ఫార్మాటింగ్ ఎలా పనిచేస్తుందో మన ఆన్‌లైన్ C# కంపైలర్‌లో స్వయంగా పరీక్షించండి!

Online C# Compiler ఓపెన్ చేయండి ➔

12 కామన్ మిస్టేక్స్ & కంపైలర్ వార్నింగ్స్ (Troubleshooting Guide)

C# వేరియబుల్స్ మరియు టైప్స్‌తో పనిచేసేటప్పుడు బిగినర్లు చేసే 4 సాధారణ తప్పులు:

ఎర్రర్ కోడ్ / సమస్య తప్పు కోడ్ ఉదాహరణ సరైన మార్గం & వివరణ
CS0664: Suffix Missing float f = 3.14; float f = 3.14f; — డీఫాల్ట్‌గా ప్రతి దశాంశ సంఖ్య double కాబట్టి float కి 'f', decimal కి 'm' తప్పక ఇవ్వాలి.
పూర్ణాంకాల విభజన ట్రాంకేషన్ double res = 5 / 2; // res = 2.0 double res = 5.0 / 2; // res = 2.5 — రెండు పూర్ణాంకాలను భాగిస్తే ఫలితం పూర్ణాంకమే వస్తుంది! కనీసం ఒకదాన్ని ఫ్లోట్ చేయాలి.
CS0165: Unassigned Variable int count; Console.WriteLine(count); int count = 0; — లోకల్ వేరియబుల్స్‌ను ఇనిషియలైజ్ చేయకుండా చదవడం కంపైలర్ నిరాకరిస్తుంది.
CS0131: L-value required const int Max = 100; Max = 200; const విలువను ప్రోగ్రామ్‌లో ఎక్కడా సవరించలేము. రన్‌టైమ్‌లో మారాలంటే సాధారణ వేరియబుల్ వాడండి.

13 సారాంశం, ఇంటర్వ్యూ ప్రశ్నలు & సెల్ఫ్-అసెస్మెంట్ క్విజ్

కీలక సారాంశం (Key Takeaways):

  • CTS Architecture: .NET లో ప్రతి టైప్ System.Object నుండే మొదలవుతుంది.
  • Value vs Reference: వాల్యూ టైప్స్ స్టాక్‌లో డీప్ కాపీ అవుతాయి; రిఫరెన్స్ టైప్స్ హీప్ లో ఉండి షాలో రిఫరెన్స్ కాపీ అవుతాయి.
  • Decimal Precision: ద్రవ్య లావాదేవీలకు రౌండింగ్ ఎర్రర్లు లేని decimal (128-bit) వాడాలి.
  • Boxing & Unboxing: స్టాక్ నుండి హీప్ కి మారడం బాక్సింగ్; దీనిని నివారించడానికి Generics వాడాలి.
  • var vs const: var అనేది కంపైల్-టైమ్ టైప్ ఇన్ఫరెన్స్; const కంపైల్-టైమ్ స్థిర విలువ.
  • Nullable Types: int? ద్వారా వాల్యూ టైప్స్‌లో కూడా null నిల్వ చేయవచ్చు.

టాప్ 5 C# వేరియబుల్స్ & డేటా టైప్స్ ఇంటర్వ్యూ ప్రశ్నలు:

  1. Q1: Value Types మరియు Reference Types మధ్య ప్రధాన వ్యత్యాసం ఏమిటి?
    జవాబు: Value Types (int, struct, enum) తమ డేటాను నేరుగా స్టాక్ మెమరీలో నిల్వ చేసుకుంటాయి మరియు కాపీ చేసినప్పుడు సరికొత్త విలువ కాపీ అవుతుంది. Reference Types (class, string, array) తమ డేటాను హీప్‌లో భద్రపరిచి, ఆ మెమరీ చిరునామాను మాత్రమే స్టాక్‌లో ఉంచుకుంటాయి; కాపీ చేసినప్పుడు అదే అడ్రస్‌ను షేర్ చేసుకుంటాయి.
  2. Q2: బాక్సింగ్ (Boxing) అంటే ఏమిటి? ఇది అప్లికేషన్ వేగాన్ని ఎందుకు తగ్గిస్తుంది?
    జవాబు: స్టాక్‌లో ఉన్న ఒక Value Type ని హీప్‌లోని object రిఫరెన్స్‌లోకి మార్చడాన్ని బాక్సింగ్ అంటారు. ఇది జరిగిన ప్రతిసారీ హీప్‌లో కొత్త మెమరీ కేటాయింపు జరిగి, పాతబడినప్పుడు Garbage Collector పై అనవసరమైన భారం పడుతుంది.
  3. Q3: const మరియు readonly మధ్య తేడా ఏమిటి?
    జవాబు: const విలువ కంపైల్ చేసేప్పుడే తెలిసి ఉండాలి మరియు IL కోడ్‌లో నేరుగా హార్డ్‌కోడ్ అవుతుంది. readonly విలువను రన్‌టైమ్‌లో కన్‌స్ట్రక్టర్ ద్వారా కూడా లెక్కించి కేటాయించవచ్చు.
  4. Q4: C# లో var కీవర్డ్ డైనమిక్ లాంగ్వేజ్ లాంటిదా?
    జవాబు: కాదు! C# లో var అనేది స్ట్రిక్ట్ కంపైల్-టైమ్ టైప్ ఇన్ఫరెన్స్. కోడ్ కంపైల్ అయ్యే సమయంలోనే కంపైలర్ దాని టైప్‌ను స్థిరీకరిస్తుంది. రన్‌టైమ్‌లో వేరే టైప్‌లోకి మారడానికి వీల్లేదు.
  5. Q5: ఫైనాన్షియల్ ప్రాజెక్ట్‌లలో double కాకుండా decimal ఎందుకు వాడాలి?
    జవాబు: double అనేది Base-2 బైనరీ ఫ్లోటింగ్ పాయింట్ (IEEE 754), దీనివల్ల 0.1 + 0.2 లాంటి సాధారణ కూడికలలో కూడా రౌండింగ్ ఎర్రర్లు వస్తాయి. decimal అనేది 128-బిట్ Base-10 రూపంలో పనిచేస్తూ 28-29 ఖచ్చితమైన దశాంశ అంకెలను అందిస్తుంది.

ఇంటరాక్టివ్ సెల్ఫ్-అసెస్మెంట్ క్విజ్ (Self-Assessment Quiz):

❓ ప్రశ్న 1: C# లో string అనేది Value Type ఆ లేక Reference Type ఆ?
సమాధానం: string అనేది ఒక Reference Type! దీని డేటా హీప్ మెమరీలో స్టోర్ అవుతుంది. అయితే ఆపరేటర్ల విషయంలో ఇది ఒక వాల్యూ టైప్ లాగా సహజంగా ప్రవర్తించేలా మైక్రోసాఫ్ట్ ఇమ్యుటబుల్ (Immutable) గా డిజైన్ చేసింది.
❓ ప్రశ్న 2: int a = 10; object obj = a; int b = (int)obj; — ఇందులో బాక్సింగ్ ఎక్కడ, అన్‌బాక్సింగ్ ఎక్కడ జరిగాయి?
సమాధానం: object obj = a; లైన్‌లో బాక్సింగ్ జరిగింది (స్టాక్ నుండి హీప్ ఆబ్జెక్ట్ గా). int b = (int)obj; లైన్‌లో అన్‌బాక్సింగ్ జరిగింది (హీప్ ఆబ్జెక్ట్ నుండి తిరిగి స్టాక్ పూర్ణాంకంగా).
❓ ప్రశ్న 3: var price = 99.99; అని రాస్తే దాని టైప్ ఏమవుతుంది?
సమాధానం: double అవుతుంది! ఎందుకంటే C# లో ఏ సఫిక్స్ లేని దశాంశ సంఖ్యలను కంపైలర్ డీఫాల్ట్‌గా double గా పరిగణిస్తుంది. decimal కావాలంటే 99.99m అని రాయాలి.
❓ ప్రశ్న 4: int? x = null; int y = x ?? 50; — y లోకి ఏ విలువ వస్తుంది?
సమాధానం: 50 వస్తుంది. ?? (Null-Coalescing) ఆపరేటర్ ఎడమవైపు ఉన్న x నల్ కాబట్టి కుడివైపు ఉన్న 50 ని y కి కేటాయిస్తుంది.
❓ ప్రశ్న 5: .NET లోని అన్ని డేటా టైప్స్‌కు అల్టిమేట్ రూట్ బేస్ క్లాస్ ఏది?
సమాధానం: System.Object (C# లో object కీవర్డ్).
← Prev: 01. C# & .NET 8 పరిచయం Next: 03. యూజర్ ఇన్‌పుట్ & టైప్ కాస్టింగ్ →
OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on .NET 8 SDK / C# 12 runtime · 2026 Academic Edition