C# యూజర్ ఇన్పుట్ (Console.ReadLine), టైప్ కాస్టింగ్ & Parse / TryParse
స్వాగతం అధ్యాయం 03 కి! 🚀 యూజర్తో ఇంటరాక్షన్ & నమ్మకమైన డేటా మార్పిడి
ఒక కంప్యూటర్ ప్రోగ్రామ్ నిజమైన సాఫ్ట్వేర్గా మారేది ఎప్పుడంటే — అది కేవలం తెరపై ఏదో ప్రింట్ చేయడం మాత్రమే కాకుండా, బయటి ప్రపంచం (యూజర్) నుండి సమాచారాన్ని స్వీకరించి, దాన్ని సమర్థవంతంగా విశ్లేషించి సరైన నిర్ణయాలు తీసుకున్నప్పుడు మాత్రమే! ఏటీఎం మెషిన్లో పిన్ ఎంటర్ చేయడం నుండి ఆన్లైన్ షాపింగ్లో ఆర్డర్ పరిమాణం ఇవ్వడం వరకు ప్రతిచోటా యూజర్ ఇన్పుట్ కీలక పాత్ర పోషిస్తుంది.
అయితే ఇక్కడ సాఫ్ట్వేర్ ఇంజనీర్లకు ఎదురయ్యే అతిపెద్ద సవాలు ఏమిటంటే: కీబోర్డ్ నుండి యూజర్ టైప్ చేసే ప్రతి అక్షరం లేదా సంఖ్య కంప్యూటర్కు కేవలం టెక్స్ట్ (string) రూపంలోనే చేరుతుంది! యూజర్ 500 అని టైప్ చేస్తే, అది గణిత సంఖ్య కాదు, కేవలం '5', '0', '0' అనే మూడు అక్షరాల స్ట్రింగ్ మాత్రమే. ఆ స్ట్రింగ్ను సరైన సంఖ్యగా మార్చి క్యాలిక్యులేషన్ చేయడంలో చిన్న తప్పు జరిగినా అప్లికేషన్ క్రాష్ అయిపోతుంది.
ఈ సమగ్ర 3వ అధ్యాయంలో మనం కన్సోల్ ఇన్పుట్ మెకానిజమ్స్ (ReadLine, ReadKey), టైప్ కాస్టింగ్ నిబంధనలు (Widening vs Narrowing), డేటా ఓవర్ఫ్లో రక్షణ (checked/unchecked), మరియు ఎంటర్ప్రైజ్ .NET సిస్టమ్స్లో వాడే రక్షిత టెక్నిక్ TryParse() డిఫెన్సివ్ ప్రోగ్రామింగ్ను లోతుగా నేర్చుకోబోతున్నాం!
1 రియల్-వరల్డ్ ప్రోగ్రామింగ్లో ఇన్పుట్ & టైప్ కన్వర్షన్ ఎందుకు గుండెకాయ వంటిది?
గత అధ్యాయంలో మనం C# లోని వివిధ డేటా టైప్స్ (int, double, decimal, string) గురించి నేర్చుకున్నాం. కోడ్లో మనమే డైరెక్ట్గా int age = 25; అని రాస్తే దాన్ని హార్డ్కోడెడ్ డేటా (Hardcoded Data) అంటారు. కానీ నిజ జీవితంలో ఒక బ్యాంకింగ్ యాప్ లేదా ఈ-కామర్స్ యాప్ రాస్తున్నప్పుడు వయస్సు లేదా నగదు డిపాజిట్ ఎంత అనేది యూజర్ మాత్రమే నిర్ణయిస్తాడు.
ఆపరేటింగ్ సిస్టమ్ ఆర్కిటెక్చర్ ప్రకారం, కీబోర్డ్ నుండి యూజర్ ఏది టైప్ చేసినా అది స్టాండర్డ్ ఇన్పుట్ స్ట్రీమ్ (stdin) ద్వారా టెక్స్ట్ బఫర్లోకి చేరుతుంది. కాబట్టి C# రన్టైమ్ దాన్ని స్వతహాగా కేవలం ఒక టెక్స్ట్ స్ట్రింగ్ (String) గానే గుర్తిస్తుంది.
మీరు యూజర్ని రెండు నంబర్లు అడిగారనుకుందాం. యూజర్ 20 మరియు 30 ఇచ్చాడు. మీరు వాటిని స్ట్రింగ్స్ గానే ఉంచి + ఆపరేటర్ వాడితే, కంప్యూటర్ వాటిని నంబర్లుగా కూడదు! బదులుగా స్ట్రింగ్ కంకాటెనేషన్ చేసి "2030" అనే సమాధానాన్ని ఇస్తుంది! దీనివల్ల బ్యాంక్ అకౌంట్ బ్యాలెన్స్ ₹50 బదులు ₹2030 చూపించి బ్యాంక్ దివాలా తీస్తుంది. అందుకే స్ట్రింగ్ను నంబర్గా మార్చే Type Conversion అత్యంత ప్రధానమైన ప్రాసెస్.
C# లో టైప్ కన్వర్షన్ చేయడానికి ప్రధానంగా 4 దారులు ఉన్నాయి:
- Implicit Casting (ఆటోమేటిక్ వైడనింగ్): చిన్న డేటా టైప్ నుండి పెద్ద డేటా టైప్కి ఎటువంటి డేటా లాస్ లేకుండా కంపైలర్ స్వయంగా చేసే మార్పిడి.
- Explicit Casting (మాన్యువల్ న్యాకోవింగ్): డేటా లాస్ అయ్యే ప్రమాదం ఉన్నప్పటికీ ప్రోగ్రామర్ బాధ్యత తీసుకొని
(int)valueరూపంలో బలవంతంగా చేసే మార్పిడి. - Convert Helper Class: .NET లైబ్రరీ అందించే
Convert.ToInt32()వంటి సమగ్ర మెథడ్స్ (ఇవిnullవిలువలను సురక్షితంగా హ్యాండిల్ చేస్తాయి). - Parsing Methods (
Parse()&TryParse()): టెక్స్ట్ స్ట్రింగ్ను సంఖ్యలుగా మార్చే ప్రత్యేక సాధనాలు. వీటిలోTryParse()క్రాష్ రహిత ప్రొడక్షన్ కోడ్కి మూలస్తంభం.
2 ⌨️ Console.ReadLine(), Console.ReadKey() & Console.Read() — తేడాలు మరియు పనితీరు
C# లో System.Console క్లాస్ యూజర్ నుండి ఇన్పుట్ తీసుకోవడానికి మూడు వేర్వేరు మెథడ్స్ను అందిస్తుంది. చాలామంది బిగినర్స్ కేవలం ReadLine() మాత్రమే వాడతారు, కానీ ప్రొఫెషనల్ ప్రాజెక్ట్స్లో మిగిలిన రెండింటి ప్రాముఖ్యత అపారం.
1. Console.ReadLine() — పూర్తి లైన్ చదవడం
యూజర్ కీబోర్డ్పై టైప్ చేసి Enter కీ నొక్కే వరకు వేచి ఉండి, అంతవరకు టైప్ చేసిన మొత్తం అక్షరాలను ఒకే స్ట్రింగ్గా రిటర్న్ చేస్తుంది.
మోడ్రన్ C# 12 Nullable Reference Warning (CS8600):
మీరు string name = Console.ReadLine(); అని రాస్తే VS Code లో లేదా కంపైలర్లో పసుపు పచ్చ వార్నింగ్ వస్తుంది: "Converting null literal or possible null value to non-nullable type". ఎందుకంటే యూజర్ కన్సోల్లో ఏమీ ఎంటర్ చేయకుండా Ctrl+Z (End-of-File) కొడితే ReadLine() null రిటర్న్ చేయవచ్చు. కాబట్టి ప్రొఫెషనల్ కోడ్లో ఇలా రాయాలి:
// Option A: Nullable string వాడటం (సిఫార్సు చేయబడినది)
Console.Write("మీ పేరు టైప్ చేయండి: ");
string? name = Console.ReadLine();
// Option B: Null Coalescing ఆపరేటర్ (??) తో డీఫాల్ట్ విలువ ఇవ్వడం
Console.Write("నగరం పేరు: ");
string city = Console.ReadLine() ?? "హైదరాబాద్";
Console.WriteLine($"నమస్కారం, {name}! మీరు {city} నుండి లాగిన్ అయ్యారు.");
2. Console.ReadKey() — సింగిల్ కీ మరియు సీక్రెట్ పాస్వర్డ్స్
యూజర్ Enter కొట్టే వరకు ఆగదు! కీబోర్డ్పై ఏదైనా ఒక కీ తాకగానే వెంటనే రియాక్ట్ అవుతుంది. ఇది ఒక ConsoleKeyInfo ఆబ్జెక్ట్ను ఇస్తుంది, అందులో ఏ కీ నొక్కారు (Key), దాని అక్షరం ఏమిటి (KeyChar), Shift లేదా Ctrl నొక్కారా లేదా అనే వివరాలు ఉంటాయి.
ముఖ్యంగా Console.ReadKey(intercept: true) అని ఇస్తే, యూజర్ నొక్కిన కీ తెరపై కనపడదు (స్క్రీన్ పై ప్రింట్ అవ్వకుండా ఇంటర్సెప్ట్ అవుతుంది). బ్యాంకింగ్ పాస్వర్డ్లు, గేమ్స్ (WASD బాణాలు), లేదా "ప్రోగ్రామ్ ముగించడానికి ఏదైనా కీ నొక్కండి..." లాంటి సందర్భాల్లో ఇది అమూల్యం.
// రహస్య పిన్ నంబర్ రీడ్ చేస్తూ తెరపై నక్షత్రాలు (*) చూపించడం
Console.Write("4-అంకెల ATM పిన్ ఎంటర్ చేయండి: ");
string pin = "";
while (true)
{
ConsoleKeyInfo keyInfo = Console.ReadKey(intercept: true); // తెరపై ప్రింట్ కాదు
if (keyInfo.Key == ConsoleKey.Enter) break; // Enter కొట్టగానే ఆగిపోతుంది
if (char.IsDigit(keyInfo.KeyChar))
{
pin += keyInfo.KeyChar;
Console.Write("*"); // యూజర్ చూసేది కేవలం నక్షత్రం మాత్రమే!
}
}
Console.WriteLine($"\nపిన్ విజయవంతంగా స్వీకరించబడింది! పొడవు: {pin.Length} అంకెలు.");
3. Console.Read() — ఒకే క్యారెక్టర్ యొక్క పూర్ణాంక విలువ
ఇది ఇన్పుట్ స్ట్రీమ్ నుండి ఒక్క క్యారెక్టర్ను చదివి దాని యొక్క పూర్ణాంక (ASCII / Unicode int) విలువను ఇస్తుంది. ఒకవేళ ఇన్పుట్ ఏమీ లేకపోతే -1 ఇస్తుంది. సాధారణంగా లో-లెవల్ స్ట్రీమ్ ప్రాసెసింగ్ మినహా ఆధునిక అప్లికేషన్లలో దీన్ని చాలా అరుదుగా వాడతారు.
3 🔄 ఇంప్లిసిట్ టైప్ కాస్టింగ్ (Implicit Type Casting / Type Widening)
C# కంపైలర్ చాలా తెలివైనది మరియు భద్రతకు అత్యధిక ప్రాధాన్యత ఇస్తుంది. ఒక చిన్న మెమరీ కంటైనర్లో ఉన్న డేటాను తీసుకొని పెద్ద మెమరీ కంటైనర్లో వేస్తే ఎటువంటి డేటా ఒలకదు లేదా నష్టపోదు అని కంపైలర్కు నమ్మకం కుదిరినప్పుడు, అది ఎటువంటి ఎర్రర్ లేకుండా ఆటోమేటిక్గా టైప్ మార్చేస్తుంది. దీనినే ఇంప్లిసిట్ కాస్టింగ్ (Implicit Casting) లేదా టైప్ వైడనింగ్ (Type Widening) అంటారు.
నిజ జీవిత ఉపమానం: మీ దగ్గర 250 మిల్లీలీటర్ల గ్లాసులో నీరు ఉంది. దాన్ని తీసుకెళ్లి 5 లీటర్ల పెద్ద బకెట్లో పోస్తే ఒక్క చుక్క కూడా బయట పడదు. అలాగే int (4 బైట్లు) లో ఉన్న 100 ని long (8 బైట్లు) లేదా double (8 బైట్లు) లోకి మార్చినా దాని విలువలో ఎటువంటి మార్పు ఉండదు.
int studentMarks = 95; // 4 బైట్ల పూర్ణాంకం
long bigRegisterId = studentMarks; // ఆటోమేటిక్ వైడనింగ్ (int to long)
double percentage = studentMarks; // ఆటోమేటిక్ వైడనింగ్ (int to double)
Console.WriteLine($"Original int: {studentMarks}");
Console.WriteLine($"Converted long: {bigRegisterId}");
Console.WriteLine($"Converted double: {percentage:F2}"); // 95.00
ముఖ్య గమనిక: ఇంప్లిసిట్ కాస్టింగ్లో మనం ఎటువంటి ప్రత్యేక బ్రాకెట్లు (type) రాయవలసిన అవసరం లేదు. కంపైలర్ తనంతట తానుగానే సిలికాన్ రిజిస్టర్లను అప్స్కేల్ చేస్తుంది.
4 ⚠️ ఎక్స్ప్లిసిట్ టైప్ కాస్టింగ్ (Explicit Type Casting / Type Narrowing) & డేటా లాస్
ఇప్పుడు రివర్స్ పరిస్థితిని ఆలోచించండి. 5 లీటర్ల బకెట్ నిండా ఉన్న నీటిని 250 మిల్లీలీటర్ల చిన్న గ్లాసులోకి పోయడానికి ప్రయత్నిస్తే ఏమవుతుంది? ఖచ్చితంగా నీరంతా నేలపాలైపోతుంది! కంప్యూటర్ ప్రోగ్రామింగ్లో కూడా పెద్ద మెమరీ సైజు గల వేరియబుల్ను చిన్న మెమరీ సైజు గల వేరియబుల్లోకి బలవంతంగా కుక్కినప్పుడు డేటా నష్టం జరుగుతుంది. దీనిని ఎక్స్ప్లిసిట్ కాస్టింగ్ (Explicit Casting) లేదా టైప్ న్యారోయింగ్ (Type Narrowing) అంటారు.
కంపైలర్ దీనిని ఆటోమేటిక్గా చేయడానికి అస్సలు ఒప్పుకోదు! ఒకవేళ మీరు int x = 99.85; అని రాస్తే, కంపైలర్ ఎర్రర్ కొడుతుంది. "నేను నా స్వంత పూచీకత్తుపై చేస్తున్నాను, డేటా పోయినా నాదే బాధ్యత" అని ప్రోగ్రామర్ బ్రాకెట్లలో కాస్ట్ ఆపరేటర్ రాయాలి: (int)99.85;.
double productPrice = 999.89;
// ఎక్స్ప్లిసిట్ కాస్టింగ్: డెసిమల్ భాగం కత్తిరించబడుతుంది (Truncation)
int roundedPrice = (int)productPrice;
Console.WriteLine($"అసలు ధర: {productPrice}");
Console.WriteLine($"కాస్ట్ చేసిన పూర్ణాంక విలువ: {roundedPrice}"); // 999 మాత్రమే వస్తుంది! 1000 కాదు!
// బిట్ ఓవర్ఫ్లో ప్రమాదం (Bit-Level Truncation):
int massiveNumber = 300;
byte smallByte = (byte)massiveNumber; // byte గరిష్ట పరిమితి 255 మాత్రమే!
Console.WriteLine($"Original int: {massiveNumber}");
Console.WriteLine($"Byte result after overflow: {smallByte}"); // 44 మాత్రమే వస్తుంది!!
బైనరీలో 300 అంటే 00000001 00101100 (9 బిట్లు). కానీ byte కేవలం ఆఖరి 8 బిట్లను మాత్రమే నిల్వ చేయగలదు. కాబట్టి మొదటి బిట్ 1 కత్తిరించబడిపోగా, మిగిలిన 8 బిట్లు 00101100 మిగిలాయి. దీని డెసిమల్ విలువ సరిగ్గా 44! ఇలాంటి బగ్స్ సాఫ్ట్వేర్లో ఊహించని ఆర్థిక నష్టాలను కలిగిస్తాయి.
5 🛡️ checked మరియు unchecked కీవర్డ్స్ — సైలెంట్ ఓవర్ఫ్లో బగ్స్ నివారణ
డీఫాల్ట్గా C# లో పూర్ణాంకాల గణితం (Integer Arithmetic) unchecked మోడ్లో నడుస్తుంది. అంటే ఒక వేరియబుల్ తన గరిష్ట పరిమితిని దాటితే (ఉదాహరణకు int.MaxValue + 1), రన్టైమ్ ఎటువంటి ఎర్రర్ లేదా అలర్ట్ ఇవ్వకుండా నెగటివ్ నంబర్గా మారిపోతుంది (దీన్నే సైలెంట్ రాప్అరౌండ్ అంటారు).
కానీ మిషన్-క్రిటికల్ ప్రాజెక్ట్స్లో (రాకెట్ లాంచ్ సాఫ్ట్వేర్, మెడికల్ పరికరాలు, బ్యాంకింగ్ లెక్కలు) ఇలా సైలెంట్గా తప్పు విలువలు రావడం మహాప్రమాదం. దీనికి పరిష్కారంగా C# మనకు checked అనే ప్రత్యేక రక్షిత బ్లాక్ను ఇచ్చింది!
int maxMoney = int.MaxValue; // 2,147,483,647
// 1. Unchecked (Default) - సైలెంట్ బగ్
int broken = unchecked(maxMoney + 1);
Console.WriteLine($"Unchecked result: {broken}"); // -2,147,483,648 (నెగటివ్ అయిపోయింది!)
// 2. Checked - పూర్తి రక్షణ (Exception విసురుతుంది)
try
{
checked
{
Console.WriteLine("రక్షిత కాలిక్యులేషన్ మొదలవుతోంది...");
int safeMoney = maxMoney + 1; // ఇక్కడ OverflowException వస్తుంది
Console.WriteLine(safeMoney);
}
}
catch (OverflowException ex)
{
Console.WriteLine($"🚨 సేఫ్టీ గార్డ్ అలర్ట్: మెమరీ పరిమితి దాటింది! {ex.Message}");
}
6 🧰 Convert క్లాస్ — విశ్వసనీయమైన ఆల్-రౌండర్ కన్వర్షన్ సాధనం
C# బేస్ క్లాస్ లైబ్రరీ (BCL) లోని System.Convert క్లాస్ ఒక స్విస్-ఆర్మీ నైఫ్ లాంటిది. ఇది ఏదైనా ఒక డేటా టైప్ నుండి మరొక డేటా టైప్కి మార్చడానికి పదుల సంఖ్యలో స్టాటిక్ మెథడ్స్ను అందిస్తుంది:
Convert.ToInt32(val)➔ 32-బిట్ పూర్ణాంకం (int) గా మారుస్తుంది.Convert.ToInt64(val)➔ 64-బిట్ పూర్ణాంకం (long) గా మారుస్తుంది.Convert.ToDouble(val)➔ ఫ్లోటింగ్ పాయింట్ (double) గా మారుస్తుంది.Convert.ToDecimal(val)➔ ఖచ్చితమైన కరెన్సీ (decimal) గా మారుస్తుంది.Convert.ToBoolean(val)➔ బూలియన్ (bool) గా మారుస్తుంది ("true", "false", 1, 0).Convert.ToString(val)➔ ఏదైనా వేరియబుల్ను స్ట్రింగ్ రూపంలోకి మారుస్తుంది.
Convert క్లాస్ యొక్క 2 సూపర్ పవర్స్:
1. Null-Safety (నల్ విలువను క్షమించడం):
మీరు (int)nullVar అని క్యాస్ట్ చేస్తే కంపైలర్ ఎర్రర్ ఇస్తుంది లేదా రన్టైమ్ లో క్రాష్ అవుతుంది. కానీ Convert.ToInt32(null) అని పిలిస్తే ఎటువంటి ఎక్సెప్షన్ రాదు! అది నిశ్శబ్దంగా సురక్షితమైన డీఫాల్ట్ విలువ 0 ని రిటర్న్ చేస్తుంది! డేటాబేస్ నుండి వచ్చే ఖాళీ రికార్డులను రీడ్ చేసేటప్పుడు ఇది ఎంతో ఉపయోగపడుతుంది.
2. Banker's Rounding (రౌండ్-టు-ఈవెన్ రూల్):
మనం సాధారణ క్యాస్టింగ్ (int)4.5 చేస్తే అది కేవలం డెసిమల్ను తుడిచేసి 4 ఇస్తుంది. కానీ Convert.ToInt32(4.5) మరియు Convert.ToInt32(5.5) రెండూ కూడా సమీపంలో ఉన్న సరిసంఖ్య (Even Number) వైపుకు రౌండ్ చేస్తాయి! దీనివల్ల గణాంకాల విశ్లేషణలో క్రమబద్ధమైన లోపాలు (Systematic Bias) తగ్గుతాయి.
string strNumber = "500";
int parsedInt = Convert.ToInt32(strNumber);
string? nullString = null;
int safeZero = Convert.ToInt32(nullString); // ఎర్రర్ రాదు, 0 వస్తుంది!
Console.WriteLine($"Null safe conversion: {safeZero}");
// Banker's Rounding తనిఖీ:
Console.WriteLine($"Convert.ToInt32(4.5) = {Convert.ToInt32(4.5)}"); // 4 (Even)
Console.WriteLine($"Convert.ToInt32(5.5) = {Convert.ToInt32(5.5)}"); // 6 (Even)
// Boolean conversion:
bool flag = Convert.ToBoolean("true");
bool numFlag = Convert.ToBoolean(1); // 1 అంటే true, 0 అంటే false
Console.WriteLine($"Boolean flags: {flag}, {numFlag}");
7 💥 Parse() మెథడ్స్ — స్ట్రింగ్ టు ప్రిమిటివ్ టైప్స్ (మరియు దాగి ఉన్న గనులు)
C# లోని ప్రతి ప్రిమిటివ్ డేటా టైప్ వద్ద స్ట్రింగ్ను రీడ్ చేయడానికి ఒక బిల్ట్-ఇన్ Parse() మెథడ్ ఉంటుంది: int.Parse(), double.Parse(), decimal.Parse(), DateTime.Parse().
స్ట్రింగ్లో ఉన్న డేటా 100% పక్కాగా సరైన ఫార్మాట్లో ఉందని మీకు గ్యారెంటీ ఉన్నప్పుడు ఇది చాలా వేగంగా పనిచేస్తుంది. ఉదాహరణకు int.Parse("450") మీకు చక్కగా 450 అనే సంఖ్యను ఇస్తుంది.
యూజర్ నుండి వచ్చే ఇన్పుట్పై నమ్మకం పెట్టుకొని గుడ్డిగా int.Parse(Console.ReadLine()) అని రాస్తే ఈ క్రింది 3 సందర్భాలలో మీ మొత్తం సాఫ్ట్వేర్ క్రాష్ అయిపోతుంది:
- ArgumentNullException: యూజర్ ఏమీ టైప్ చేయకుండా ఖాళీగా వదిలేస్తే (
null). - FormatException: సంఖ్యకు బదులు అక్షరాలు టైప్ చేస్తే (ఉదా:
"abc"లేదా"12.5"ని int లోకి పాస్ చేస్తే). - OverflowException: డేటా టైప్ సైజు కంటే పెద్ద సంఖ్య ఇస్తే (ఉదా:
"999999999999999"ని int లోకి పాస్ చేస్తే).
try
{
Console.Write("మీ వయస్సు టైప్ చేయండి: ");
string? rawInput = Console.ReadLine();
// ఒకవేళ యూజర్ "ఇరవై" లేదా "twenty" అని రాస్తే ఇక్కడ క్రాష్ అవుతుంది!
int age = int.Parse(rawInput!);
Console.WriteLine($"వచ్చే ఏడాదికి మీ వయస్సు: {age + 1}");
}
catch (FormatException)
{
Console.WriteLine("ఎర్రర్: దయచేసి కేవలం అంకెలు మాత్రమే టైప్ చేయండి!");
}
catch (OverflowException)
{
Console.WriteLine("ఎర్రర్: మీరు ఇచ్చిన సంఖ్య చాలా పెద్దదిగా ఉంది!");
}
ప్రతి చిన్న ఇన్పుట్కి ఇంత పెద్ద try-catch బ్లాక్ రాయడం కోడ్ క్లట్టర్కు దారితీస్తుంది మరియు ఎక్సెప్షన్ హ్యాండ్లింగ్ సిస్టమ్ రిసోర్సెస్ను విపరీతంగా వాడుకుంటుంది. అందుకే సీనియర్ ఆర్కిటెక్ట్స్ తర్వాతి సెక్షన్లో ఉన్న టెక్నిక్ను మాత్రమే వాడతారు!
8 🏆 గోల్డెన్ స్టాండర్డ్: TryParse() డిఫెన్సివ్ ప్రోగ్రామింగ్ & out పారామీటర్స్
ఆధునిక C# లో యూజర్ ఇన్పుట్ లేదా ఎక్స్టర్నల్ ఫైల్ డేటాను ప్రాసెస్ చేయడానికి TryParse() ను గోల్డెన్ స్టాండర్డ్ (Golden Standard) గా పరిగణిస్తారు.
TryParse ఎలా పనిచేస్తుంది?
ఇది ఎట్టి పరిస్థితుల్లోనూ ఎక్సెప్షన్ విసరదు! కన్వర్షన్ విజయవంతమైతే true రిటర్న్ చేస్తుంది మరియు మార్చబడిన విలువను out పారామీటర్లో భద్రపరుస్తుంది. ఒకవేళ ఇన్పుట్ తప్పుగా ఉంటే (అక్షరాలు, నల్, పరిమితి దాటినా) నిశ్శబ్దంగా false రిటర్న్ చేస్తుంది మరియు out వేరియబుల్ను 0 గా సెట్ చేస్తుంది.
Console.Write("మీ డిపాజిట్ మొత్తం ఎంటర్ చేయండి (రూపాయలు): ");
string? input = Console.ReadLine();
// C# 7+ Inline Out Variable Declaration
if (decimal.TryParse(input, out decimal depositAmount) && depositAmount > 0)
{
Console.WriteLine($"✅ ధృవీకరించబడింది! జమ చేయబడిన మొత్తం: ₹{depositAmount:N2}");
}
else
{
Console.WriteLine("❌ చెల్లని మొత్తం! దయచేసి సరైన ధనాత్మక సంఖ్యను నమోదు చేయండి.");
}
యూజర్ సరైన సంఖ్య ఇచ్చే వరకు అడిగే అజేయమైన లూప్ (Foolproof Input Loop):
రియల్ వరల్డ్ అప్లికేషన్లలో యూజర్ తప్పు ఇన్పుట్ ఇచ్చినప్పుడు ప్రోగ్రామ్ ముగిసిపోకూడదు. సరైన ఇన్పుట్ ఇచ్చే వరకు యూజర్ని తిరిగి తిరిగి అడగాలి. ఈ క్రింది ప్యాటర్న్ ప్రొఫెషనల్ కోడింగ్లో అత్యంత ప్రాచుర్యం పొందింది:
int validAge;
while (true)
{
Console.Write("మీ వయస్సు నమోదు చేయండి (1 - 120): ");
string? text = Console.ReadLine();
if (int.TryParse(text, out validAge) && validAge >= 1 && validAge <= 120)
{
break; // సరైన వయస్సు లభించింది! లూప్ నుండి బయటపడవచ్చు
}
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("తప్పుడు సమాచారం! దయచేసి 1 నుండి 120 మధ్య సరైన సంఖ్య ఇవ్వండి.");
Console.ResetColor();
}
Console.WriteLine($"స్వాగతం! మీ వయస్సు {validAge} సంవత్సరాలుగా నమోదు చేయబడింది.");
9 📊 తులనాత్మక పట్టిక: (int) vs int.Parse() vs Convert.ToInt32() vs int.TryParse()
ఇంటర్వ్యూలలో మరియు ఆర్కిటెక్చర్ డిజైన్లో తరచుగా అడిగే కీలకమైన తేడాలను స్పష్టమైన అవగాహన కోసం ఈ సమగ్ర పట్టికలో పరిశీలించండి:
| ఫీచర్ / బిహేవియర్ | Casting: (int)val | Parsing: int.Parse(str) | Helper: Convert.ToInt32(val) | Defensive: int.TryParse(str, out res) |
|---|---|---|---|---|
| ఇన్పుట్ టైప్స్ | సంఖ్యా రకాలు (double, float, byte...) | కేవలం string మాత్రమే |
ఏదైనా ఆబ్జెక్ట్ (string, double, null, bool...) | కేవలం string లేదా ReadOnlySpan<char> |
| Null ఇచ్చినప్పుడు | కంపైల్ ఎర్రర్ (లేదా NRE) | ArgumentNullException (క్రాష్) |
0 రిటర్న్ చేస్తుంది (Null-Safe) | false ఇస్తుంది, res = 0 (క్రాష్ అవ్వదు) |
| తప్పుడు ఫార్మాట్ ("abc") | కంపైల్ టైమ్ లోనే ఒప్పుకోదు | FormatException (క్రాష్) |
FormatException (క్రాష్) |
false రిటర్న్ చేస్తుంది (అత్యంత సురక్షితం) |
| పరిమితి దాటినప్పుడు (> 2.14B) | బిట్ కటింగ్ (Unchecked Truncation) | OverflowException |
OverflowException |
false రిటర్న్ చేస్తుంది |
| రౌండింగ్ విధానం (9.8 కి) | ట్రంకేషన్ (9 ఇస్తుంది) | వర్తించదు (డెసిమల్ స్ట్రింగ్ ఇస్తే ఎర్రర్) | Banker's Rounding (10 ఇస్తుంది) | వర్తించదు (డెసిమల్ స్ట్రింగ్ ఇస్తే false) |
| పెర్ఫార్మెన్స్ | మెరుపు వేగం (CPU సైకిల్స్) | మధ్యస్థం (ఎర్రర్ వస్తే స్లో) | మధ్యస్థం (ఇంటర్నల్ ఓవర్హెడ్) | అత్యుత్తమం (Zero Exceptions thrown) |
| ఉత్తమ వినియోగ సందర్భం | సాఫ్ట్వేర్ అంతర్గత నంబర్లలో డేటా సైజు మార్పులకు | ఫార్మాట్ ఖచ్చితంగా సరైనదని తెలిసిన ఇంటర్నల్ ఫైల్స్ వద్ద | డేటాబేస్ నుండి వచ్చే dynamic / nullable విలువలకు | యూజర్ ఇన్పుట్, వెబ్ ఏపీఐ, ఎక్స్టర్నల్ ఫైల్స్ అన్నిటికీ! |
10 🌍 CultureInfo & ఇంటర్నేషనలైజేషన్ — డెసిమల్ పాయింట్ (.) vs కామా (,) సమస్యలు
ప్రపంచవ్యాప్తంగా సాఫ్ట్వేర్ రన్ అయ్యేటప్పుడు డెసిమల్ నంబర్లను ఎలా రాస్తారు అనే విషయంలో దేశాల మధ్య తీవ్రమైన విభేదాలు ఉన్నాయి:
- భారతదేశం, అమెరికా, బ్రిటన్: డెసిమల్ పాయింట్గా చుక్క వాడతారు (ఉదా:
10.50). - జర్మనీ, ఫ్రాన్స్, ఇటలీ, బ్రెజిల్: డెసిమల్ సెపరేటర్గా కామా వాడతారు (ఉదా:
10,50) మరియు వేల విభజనకు చుక్క వాడతారు (1.000,00).
మీరు సాధారణ double.Parse("10.50") అని రాస్తే, అది యూజర్ యొక్క కంప్యూటర్ ఆపరేటింగ్ సిస్టమ్ కల్చర్ (Regional Settings) ఆధారంగా పనిచేస్తుంది. మీ కోడ్ జర్మన్ సర్వర్లో రన్ అయినప్పుడు "10.50" ని చూసి FormatException త్రో చేస్తుంది, లేదా దాన్ని 1050 గా తప్పుగా చదువుతుంది! (10 రూపాయల వస్తువుకు 1050 రూపాయలు బిల్ చేస్తుంది).
using System.Globalization;
string priceText = "49.99";
// సర్వర్ ప్రపంచంలో ఎక్కడ ఉన్నా చుక్క (.) నే డెసిమల్ గా గుర్తించే గ్లోబల్ ప్రామాణికం
if (double.TryParse(priceText, NumberStyles.Any, CultureInfo.InvariantCulture, out double universalPrice))
{
Console.WriteLine($"గ్లోబల్ ధర విజయవంతంగా పార్స్ చేయబడింది: {universalPrice}");
}
else
{
Console.WriteLine("ధర ఫార్మాట్ చెల్లదు!");
}
ప్రొఫెషనల్ రూల్: ఆర్థిక లావాదేవీలు, వెబ్ API JSON డేటా మరియు కాన్ఫిగరేషన్ ఫైల్స్ రీడ్ చేసేటప్పుడు ఎల్లప్పుడూ CultureInfo.InvariantCulture వాడటం సీనియర్ సాఫ్ట్వేర్ ఆర్కిటెక్చర్ నియమం.
11 🚀 రియల్-వరల్డ్ ప్రాజెక్ట్: "Smart Retail Cashier & Billing Engine"
ఇప్పటివరకు మనం నేర్చుకున్న Console.ReadLine(), TryParse(), టైప్ కాస్టింగ్, రౌండింగ్, మరియు నల్ హ్యాండ్లింగ్ కాన్సెప్ట్స్ అన్నింటినీ సమన్వయం చేస్తూ — ఒక పూర్తి స్థాయి రిటైల్ సూపర్ మార్కెట్ క్యాషియర్ కౌంటర్ బిల్లింగ్ ఇంజిన్ను తయారు చేద్దాం.
ఈ ప్రాజెక్ట్ లో:
- కస్టమర్ పేరును నల్-సేఫ్గా రీడ్ చేస్తాం.
- వస్తువు పేరు, పరిమాణం (quantity), యూనిట్ ధర (price), మరియు డిస్కౌంట్ శాతాలను రక్షిత లూప్లలో స్వీకరిస్తాం.
- సబ్-టోటల్, 18% జీఎస్టీ (GST), డిస్కౌంట్ తగ్గింపుల తర్వాత తుది చెల్లింపు మొత్తాన్ని లెక్కగడతాం.
- ఆర్థిక ఖచ్చితత్వం కోసం
decimalడేటా టైప్ను మాత్రమే వాడతాం.
using System;
using System.Globalization;
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.WriteLine("=================================================");
Console.WriteLine("🛒 మన సూపర్ మార్కెట్ - స్మార్ట్ క్యాషియర్ కౌంటర్ v1.0");
Console.WriteLine("=================================================");
// 1. కస్టమర్ పేరు స్వీకరణ (Null-Coalescing)
Console.Write("కస్టమర్ పేరు నమోదు చేయండి: ");
string customerName = Console.ReadLine();
if (string.IsNullOrWhiteSpace(customerName))
{
customerName = "గౌరవనీయ కస్టమర్";
}
// 2. వస్తువు పేరు
Console.Write("వస్తువు పేరు (Item Name): ");
string itemName = Console.ReadLine() ?? "సాధారణ వస్తువు";
// 3. పరిమాణం స్వీకరణ (Defensive int.TryParse Loop)
int quantity;
while (true)
{
Console.Write("పరిమాణం (Quantity - అంకెలలో): ");
string? qInput = Console.ReadLine();
if (int.TryParse(qInput, out quantity) && quantity > 0)
{
break;
}
Console.WriteLine("❌ తప్పు! పరిమాణం కనీసం 1 లేదా అంతకంటే ఎక్కువ ఉండాలి.");
}
// 4. యూనిట్ ధర స్వీకరణ (Defensive decimal.TryParse Loop)
decimal unitPrice;
while (true)
{
Console.Write("యూనిట్ ధర (Price per item ₹): ");
string? pInput = Console.ReadLine();
if (decimal.TryParse(pInput, NumberStyles.Any, CultureInfo.InvariantCulture, out unitPrice) && unitPrice > 0)
{
break;
}
Console.WriteLine("❌ తప్పు! దయచేసి సరైన ధరను ధనాత్మక సంఖ్యలో ఇవ్వండి.");
}
// 5. డిస్కౌంట్ శాతం (0 to 50%)
decimal discountPercent;
while (true)
{
Console.Write("డిస్కౌంట్ శాతం (Discount % [0 to 50]): ");
string? dInput = Console.ReadLine();
if (decimal.TryParse(dInput, NumberStyles.Any, CultureInfo.InvariantCulture, out discountPercent)
&& discountPercent >= 0 && discountPercent <= 50)
{
break;
}
Console.WriteLine("❌ తప్పు! డిస్కౌంట్ 0 నుండి 50 శాతం మధ్య మాత్రమే ఉండాలి.");
}
// 6. బిజినెస్ లాజిక్ కాలిక్యులేషన్స్
decimal subTotal = quantity * unitPrice;
decimal discountAmount = subTotal * (discountPercent / 100m);
decimal taxableAmount = subTotal - discountAmount;
decimal gstAmount = taxableAmount * 0.18m; // 18% ప్రామాణిక GST
decimal grandTotal = taxableAmount + gstAmount;
// 7. అందమైన రసీదు (Tax Invoice) ప్రింటింగ్
Console.WriteLine("\n=================================================");
Console.WriteLine(" అధికారిక టాక్స్ ఇన్వాయిస్ ");
Console.WriteLine("=================================================");
Console.WriteLine($"తేదీ & సమయం : {DateTime.Now:dd-MMM-yyyy hh:mm tt}");
Console.WriteLine($"కస్టమర్ పేరు : {customerName}");
Console.WriteLine($"కొన్న వస్తువు : {itemName}");
Console.WriteLine($"పరిమాణం : {quantity}");
Console.WriteLine($"యూనిట్ రేటు : ₹{unitPrice:N2}");
Console.WriteLine("-------------------------------------------------");
Console.WriteLine($"సబ్-టోటల్ : ₹{subTotal:N2}");
Console.WriteLine($"డిస్కౌంట్ ({discountPercent}%) : -₹{discountAmount:N2}");
Console.WriteLine($"పన్ను పరిధి మొత్తం : ₹{taxableAmount:N2}");
Console.WriteLine($"జీఎస్టీ (GST 18%): +₹{gstAmount:N2}");
Console.WriteLine("-------------------------------------------------");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"చెల్లించాల్సిన మొత్తం: ₹{grandTotal:N2}");
Console.ResetColor();
Console.WriteLine("=================================================");
Console.WriteLine("మా వద్ద షాపింగ్ చేసినందుకు ధన్యవాదాలు! మళ్లీ రండి! 🙏\n");
ఈ పూర్తి కోడ్ను మా ఇంటరాక్టివ్ బ్రౌజర్ ఎడిటర్లో పేస్ట్ చేసి రన్ చేయండి. మీ కస్టమర్ పేరు, పరిమాణం, మరియు ధర ఇచ్చి ఆటోమేటిక్ ఇన్వాయిస్ ఎలా జెనరేట్ అవుతుందో స్వయంగా చూడండి!
12 🛑 బిగినర్స్ చేసే 7 ఘోరమైన తప్పులు & ప్రొఫెషనల్ బెస్ట్ ప్రాక్టీసెస్
ఇండస్ట్రీలో జూనియర్ డెవలపర్లు కోడ్ రాసేటప్పుడు తరచుగా చేసే 7 ముఖ్యమైన తప్పులు మరియు వాటి నివారణ మార్గాలు:
string s = Console.ReadLine(); రాస్తే వార్నింగ్ వస్తుంది. ఎల్లప్పుడూ string? వాడండి లేదా ?? "" తో శూన్యతను నిరోధించండి.
(int)9.99 ఎప్పటికీ 10 అవ్వదు, కేవలం 9 మాత్రమే అవుతుంది. రౌండింగ్ కావాలంటే Math.Round() లేదా Convert.ToInt32() వాడాలి.
బైనరీ ఫ్లోటింగ్ పాయింట్ పరిమితుల వల్ల పైసల లెక్కల్లో తేడా వస్తుంది (ఉదా: 0.1 + 0.2 = 0.30000000000000004). డబ్బు లెక్కలకు decimal మాత్రమే వాడాలి.
యూజర్ పొరపాటున అక్షరం కొట్టగానే యాప్ క్రాష్ అయిపోతుంది. ఎల్లప్పుడూ int.TryParse() నే వాడాలి.
యూరోపియన్ దేశాల్లో డెసిమల్స్ కామాతో ఉంటాయి. API ఇన్పుట్స్ పార్స్ చేసేటప్పుడు CultureInfo.InvariantCulture ను జతచేయడం మర్చిపోవద్దు.
రెండు పెద్ద ఇంటిజర్లను గుణించినప్పుడు అది 2 బిలియన్లు దాటితే సైలెంట్గా నెగటివ్ నంబర్ అయిపోతుంది. కీలక గణనలకు checked బ్లాక్ వాడండి.
int.TryParse(str, out int val); తర్వాత if కండిషన్ పెట్టకుండా డైరెక్ట్గా val వాడితే, పార్సింగ్ ఫెయిల్ అయినప్పుడు val లో 0 ఉంటుంది, అది తప్పుడు గణనలకు దారితీస్తుంది.
13 🧠 ఇంటరాక్టివ్ సెల్ఫ్-అసెస్మెంట్ క్విజ్ (5 లోతైన ప్రాక్టికల్ ప్రశ్నలు & వివరణలు)
ఈ అధ్యాయంలో నేర్చుకున్న విషయాలను ఎంతవరకు గ్రహించారో ఈ 5 ఇంటరాక్టివ్ ప్రశ్నలతో మీరే స్వయంగా పరీక్షించుకోండి!
❓ ప్రశ్న 1: int a = (int)8.99; మరియు int b = Convert.ToInt32(8.99); ఎగ్జిక్యూట్ అయితే a మరియు b విలువలు ఏమిటి?
a = 8 మరియు b = 9.వివరణ: ఎక్స్ప్లిసిట్ కాస్టింగ్
(int) కేవలం డెసిమల్ భాగాలను తుడిచిపెడుతుంది (Truncation), కాబట్టి 8.99 లో .99 పోయి 8 మిగులుతుంది. కానీ Convert.ToInt32() రౌండింగ్ నియమాలను పాటిస్తుంది, 8.99 అనేది 9 కి దగ్గరగా ఉండటం వల్ల 9 గా రౌండ్ చేస్తుంది.
❓ ప్రశ్న 2: int.Parse(null) మరియు Convert.ToInt32(null) రన్ చేస్తే ఏమి జరుగుతుంది?
int.Parse(null) రన్టైమ్లో ArgumentNullException విసిరి అప్లికేషన్ను క్రాష్ చేస్తుంది. కానీ Convert.ToInt32(null) ఎటువంటి ఎర్రర్ ఇవ్వకుండా సురక్షితంగా పూర్ణాంకం 0 ని రిటర్న్ చేస్తుంది.
❓ ప్రశ్న 3: Console.ReadKey(true) లో true పారామీటర్ యొక్క ప్రాముఖ్యత ఏమిటి?
intercept. దాని విలువ true అయితే, యూజర్ కీబోర్డ్ పై నొక్కిన క్యారెక్టర్ తెరపై కనపడదు (It hides/intercepts echo to console). రహస్య పాస్వర్డ్లు, సెన్సిటివ్ పిన్లు రీడ్ చేయడానికి దీనిని వాడతారు.
❓ ప్రశ్న 4: int.TryParse("250", out int res) లో out కీవర్డ్ ఎందుకు అవసరం?
TryParse() ఇప్పటికే పార్సింగ్ సక్సెస్ అయిందా లేదా తెలిపే bool ను రిటర్న్ చేస్తుంది. అదనంగా, కన్వర్ట్ అయిన సంఖ్యను బయటకు పంపడానికి out (Output Parameter) మెకానిజమ్ను ఉపయోగిస్తుంది.