Good day everyone. To my shame dont understand how to make it. I have a class like:
public class Worker
{
public int ID { get; set; }
}
And Data class with workers List. Have a method to work with it:
public Department GetWorkerByID (int id)
{
foreach (Worker worker in Workers)
{
if (worker.ID == id)
return worker;
}
return null;
{
The problem is i need to give the user ability to choose the current worker from list by its ID number and i want program to handle invalid input like random simbols, letters etc and check if the input ID is exist. Usually i use boolean property for this:
string input = Console.ReadLine();
bool isInt = int.TryParse(input, out _);
And so on. But in case with class properties it doesnt work like i expected and when i try to do this:
while (!isInt && Data.GetWorkerByID(int.Parse(input)) == null)
{
Console.Write("Wrong input. Try again: ");
input = Console.ReadLine();
}
Its not working, throwing me the exceptions of invalid format for ID number or pass the number but than trying to get the non existing instance of worker. Any advice welcome.
Try do something like that:
C#:
public Worker TryGetWorker()
{
string input = Console.ReadLine();
int index = -1;
bool isInt = int.TryParse(input,out index);
Worker worker = Data.GetWorkerByID(index);
if (!isInt || worker == null)
{
Console.Write("Wrong input. Try again: ");
return TryGetWorker();
}
else
return worker;
}
Related
i have fixed the question:
The code is working until it hit the MultyMethod it stop because i have tried to take the output from the SumMethod and do another calculation in the MultyMethod.
So my question is i have tried to use the same input from SumMethod in the MultyMethod but it does not work well i have used all the reference in my mind or i could think of but still it told me : the name "SumMethod" need a reference to call it or you forgetting to use a reference. So how i could use the same input from the SumMethod in the MultyMethod!!
using System;
namespace example
{
class Program
{
public int number1 { set; get; }
public int number2 { set; get; }
public int sum { set; get; }
public int multy { set; get; }
static void Main(string[] args)
{
var value = SumMethod();
var values = MultyMethod();
ResultMethod(value.number1, value.number2, value.sum, values.multy);
}
public static Program SumMethod()
{
var input = new Program();
int i = 0;
Console.WriteLine(" Please Enter your first number: ");
input.number1 = int.Parse(Console.ReadLine());
Console.WriteLine(" Please Enter your second number: ");
input.number2 = int.Parse(Console.ReadLine());
int[] arr = new int[] { input.number1, input.number2 };
do
{
input.sum += arr[i];
i++;
} while (i < 2);
return input;
}
public static Program MultyMethod()
{
var input = new Program();
// here is the issue i am trying to get the input from the previous method instead of asking the user to input the numbers again
// i have tried this
//input.number1 = new input.SumMethod();
// and also have tried to use this reference
//value.SumMethod(); // since the inputs store in this variable but it does not make since to call it this way ><
// i have also tried to use this way
//input.number1 = new SumMethod();
return input;
}
public static void ResultMethod(int number1, int number2, int sum, int multy)
{
Console.WriteLine(" The first number is: ");
Console.WriteLine(number1);
Console.WriteLine(" The second number is: ");
Console.WriteLine(number2);
Console.WriteLine(" The sum of the number is: ");
Console.WriteLine(sum);
Console.WriteLine(" The multiplication of the numbers is: ");
Console.WriteLine(multy);
}
}
}
Okay, your basic problem is that the variable input, which you wish to reference in MultyMethod, is internal to SumMethod. Therefore, MultyMethod can't access it.
You define another variable called input in MultyMethod, but that is NOT the same variable. It's a separate one, the scope of which is just MultyMethod, and can't be accessed outside of it.
So, how to do what you want. I hope you don't mind that I'm also going to make some suggestions about how you could better organize this code.
First, you could define input outside of SumMethod, as a class-level static variable. In that case, it could be accessed by both SumMethod and MultyMethod. The following is a short excerpt (with some lines removed to save space):
class Program
{
public int number1 { set; get; }
public int number2 { set; get; }
public int sum { set; get; }
public int multy { set; get; }
public static Program input = null;
static void Main(string[] args)
{
// etc.
}
public static Program SumMethod()
{
input = new Program();
// rest of the code
return input;
}
public static Program MultyMethod()
{
input = Program.input; // this is a static reference.
// desired multiplication code
return input;
}
Another option would be to parameterize MultyMethod so it takes a Program as a parameter, representing the input:
public static Program MultyMethod(Program input)
{
// You probably don't want to have the same variable have both your sum
// and your multiplication results.
Program newVar = new Program() { number1 = input.number1, number2 = input.number2 };
// Do things with newVar in place of "input"
return newVar;
}
Then you'd change Main to look like this:
var value = SumMethod();
var values = MultyMethod(value);
An even better version would separate getting the input from performing the summing. So you could do this:
static void Main(string[] args)
{
var input = GetInput();
var value = SumMethod(input);
var values = MultyMethod(input);
// do other things
}
Finally, the whole thing would be better if you had separate classes for all three of the following:
The program itself
The input parameters and results
The multiplication and sum methods
I need to allow the users choose their own path by picking between two simple choices displayed on their screen in order to progress to the next set of choices, until they get to one of the endings, i.e something like this should be achieved:
I have tried the following code, but only the left side is evaluated each time. I am wondering how can I achieve a results like the above image (covering all the branches)? For instance, if the user selects "No" the application shouldn't ask any further question from the user and just simply shows the "Maybe you want a Pizza" message. I have done this with decision tree algorithm and need to fix it, so that it covers both the left and right sides just like the above image.
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
var decisionTree = MainDecisionTree();
var client = new Client();
Console.WriteLine("Do you want a book? true/false");
client.Answer[0] = bool.Parse(Console.ReadLine());
Console.WriteLine("Do you like it? true/false");
client.Answer[1] = bool.Parse(Console.ReadLine());
Console.WriteLine("Are you sure? true/false");
client.Answer[2] = bool.Parse(Console.ReadLine());
decisionTree.Evaluate(client);
Console.WriteLine("Press any key...");
Console.ReadKey();
}
private static DecisionQuery MainDecisionTree()
{
//Decision 2
var wantBranch = new DecisionQuery
{
Title = "Do you want a book?",
Test = (client) => client.Answer[0],
Positive = new DecisionResult { Result = true },
Negative = new DecisionResult { Result = false }
};
//Decision 1
var deserveBranch = new DecisionQuery
{
Title = "Do you like it?",
Test = (client) => client.Answer[1],
Positive = wantBranch,
Negative = new DecisionResult { Result = false }
};
//Decision 0
var sureBranch = new DecisionQuery
{
Title = "Are you sure?",
Test = (client) => client.Answer[2],
Positive = deserveBranch,
Negative = new DecisionResult { Result = false }
};
return sureBranch;
}
}
public class DecisionResult : Decision
{
public bool Result { get; set; }
public override void Evaluate(Client client)
{
Console.WriteLine("\r\nThe result: {0}", Result ? "Buy it" : "You need to wait");
}
}
public class DecisionQuery : Decision
{
public string Title { get; set; }
public Decision Positive { get; set; }
public Decision Negative { get; set; }
public Func<Client, bool> Test { get; set; }
public override void Evaluate(Client client)
{
bool result = this.Test(client);
string resultAsString = result ? "yes" : "no";
Console.WriteLine($"\t- {this.Title}? {resultAsString}");
if (result) this.Positive.Evaluate(client);
else this.Negative.Evaluate(client);
}
}
public abstract class Decision
{
public abstract void Evaluate(Client client);
}
public class Client
{
public bool[] Answer { get; set; } = new bool[3];
}
}
If I understand your issue, here is your code corrected.
I renamed some things.
I called MakeDecisionTree the method that initializes the expert system with the conditions tree and it returns the root condition.
Each condition contains a sentence to evaluate and it can be a query or a result.
For a result, the evaluate display the sentence.
For a query, the evaluate method asks the user to answer the question by yes or no. And using this answer, it calls the corresponding evaluate of the next child condition.
Sorry for my english here, it is not my native language, and I'm not involved in AI.
static private void DecisionTreeTest()
{
Console.WriteLine("Please, answer a few questions with yes or no.");
Console.WriteLine();
MakeDecisionTree().Evaluate();
}
static private bool GetUserAnswer(string question)
{
Console.WriteLine(question);
string userInput;
while ( true )
{
userInput = Console.ReadLine().ToLower();
if ( userInput == "yes" )
return true;
else
if ( userInput == "no" )
return false;
else
Console.WriteLine("Your answer is not supported, retry please." +
Environment.NewLine + Environment.NewLine +
question);
}
}
static private DecisionTreeQuery MakeDecisionTree()
{
var queryAreYouSure
= new DecisionTreeQuery("Are you sure?",
new DecisionTreeResult("Buy it."),
new DecisionTreeResult("You need to wait."),
GetUserAnswer);
var queryIsItAGoodBook
= new DecisionTreeQuery("Is it a good book?",
new DecisionTreeResult("What are you waiting for? Just buy it."),
new DecisionTreeResult("Find another one."),
GetUserAnswer);
var queryDoYouLikeIt
= new DecisionTreeQuery("Do you like it?",
queryAreYouSure,
queryIsItAGoodBook,
GetUserAnswer);
var queryDoYouWantABook
= new DecisionTreeQuery("Do you want a book?",
queryDoYouLikeIt,
new DecisionTreeResult("Maybe you want a pizza."),
GetUserAnswer);
return queryDoYouWantABook;
}
abstract public class DecisionTreeCondition
{
protected string Sentence { get; private set; }
abstract public void Evaluate();
public DecisionTreeCondition(string sentence)
{
Sentence = sentence;
}
}
public class DecisionTreeQuery : DecisionTreeCondition
{
private DecisionTreeCondition Positive;
private DecisionTreeCondition Negative;
private Func<string, bool> UserAnswerProvider;
public override void Evaluate()
{
if ( UserAnswerProvider(Sentence) )
Positive.Evaluate();
else
Negative.Evaluate();
}
public DecisionTreeQuery(string sentence,
DecisionTreeCondition positive,
DecisionTreeCondition negative,
Func<string, bool> userAnswerProvider)
: base(sentence)
{
Positive = positive;
Negative = negative;
UserAnswerProvider = userAnswerProvider;
}
}
public class DecisionTreeResult : DecisionTreeCondition
{
public override void Evaluate()
{
Console.WriteLine(Sentence);
}
public DecisionTreeResult(string sentence)
: base(sentence)
{
}
}
You decision tree design is very good, just the way you ask the user is not.
You ask all the questions in advance, and go to the decision tree later on.
Of course the tree cannot make asked questions unasked.
It's not a decision tree problem.
you would have to put these pairs of lines:
Console.WriteLine("Are you sure? true/false");
client.Answer[2] = bool.Parse(Console.ReadLine());
into the Evaluate method, or you do a callback or whatever architectural design to separate logic from user-interface.
The decision-tree has to ask, or at least know the question.
The answer does not need to be stored, you can evaluate it right after input.
Maybe you pass something to Ask the user to the evaluate Method
public interface IAsk
{
bool Question(string message);
}
And for your sample you instantiate that with
public class ConsoleAsk : IAsk
{
bool Question(string message)
{
Console.WriteLine(message);
return bool.Parse(Console.ReadLine());
}
}
and you modify your Evaluate like this:
public override void Evaluate(IAsk ask)
{
bool result = ask.Question("do you feel good or bad");
string resultAsString = result ? "yes" : "no";
Console.WriteLine($"\t- {this.Title}? {resultAsString}");
if (result) this.Positive.Evaluate(ask);
else this.Negative.Evaluate(ask);
}
of course you replace the question with your title property.
I am new to C# and was wondering what I am doing wrong while working with get and set.
I have a VendingMachine that, when I input a number for the beverage that I want, it subtracts from the total.
private int _coke = 2;
public int Beer = 20;
public int LemonLime = 20;
public int Grape = 20;
public int CreamSoda = 20;
public bool AnohterBevrage;
The problem is that it keeps subtracting even after it reaches 0. Well, there cant be -1 Coke left in the Machine. So, I tried this.
public int Coke
{
get => _coke;
set
{
if (_coke == 0)
{
_coke = value;
Console.WriteLine("No more Coke Left!");
}
}
}
But it doesn't work, so I'm not sure where I'm getting stuck. I'm not sure if the Math function is relevant here.
If there is something missing, let me know. I will try and adjust. This getter and setter gets me all confused.
EDIT: Add function
public void Math()
{
var input = Console.ReadKey();
while (input.Key == ConsoleKey.D1)
{
do
{
_coke--;
Console.WriteLine("\nTotal Coke Left: " + Coke);
Console.Write("\nWould You like Another Bevrage ?y/n: ");
if (Console.ReadLine() == "y")
{
AnohterBevrage = true;
Content();
Math();
}
else
{
AnohterBevrage = false;
}
break;
} while (AnohterBevrage == true);
}
}
if (_coke == 0)
You're checking the current value.
That means that you can only set the property if it is currently 0.
When you start trying to do something, you need to build a model of what you are doing. Using getters/setters as your UI is not a great design (as #Rufus L pointed out). Instead, picture a Coke machine in your head. There are racks of various drinks (that get restocked), and then a mechanical system that implements a user interface that allows someone to pick a drink and get it delivered. You should separate your design into those two parts.
One hint that your design needs work is that your main function (that's doing all the work) is named "Math". If you were to look at this code in two months, you'd see "Math" and not have a clue it represented a Coke machine.
I wrote a quickie coke machine that matches your needs (well, I think it does). It uses that same mental model, a set of beverage racks and a controller. I did this with a simple class that represents a rack of drinks and a controller written in a console app's main routine (so everything is static).
The RackOfBeverage class (it includes a restock method that's never called):
class RackOfBeverages
{
public string Label { get; }
public int Count { get; private set; }
public RackOfBeverages(string label, int initialCount)
{
Label = label;
Count = initialCount;
}
public void Restock(int howMany)
{
Count += howMany;
}
public bool Dispense()
{
if (Count > 0)
{
--Count;
return true;
}
else
{
return false;
}
}
}
It has a label (indicating what kind of drink it is), an inventory/count and a Dispense method. The Dispense call will return false if there are no drinks left.
Then I wrote a simple controller (as the Main method in a console app along with a few other bits that I put in the Program class):
class Program
{
private static readonly Dictionary<string, RackOfBeverages> Beverages =
new Dictionary<string, RackOfBeverages>
{
{"COKE", new RackOfBeverages("Coke", 2)},
{"SPRITE", new RackOfBeverages("Sprite", 20)},
//etc.
};
static void Main(string[] args)
{
Console.WriteLine("Welcome to the machine\r\nType a selection (type \"Exit\" to quit)");
while (true)
{
var selection = Console.ReadLine();
//did the user enter the name of a drink
if (Beverages.Keys.Contains(selection, StringComparer.OrdinalIgnoreCase))
{
var beverage = Beverages[selection.ToUpper()];
//was there enough to dispense a drink
if (beverage.Dispense())
{
Console.WriteLine($"Here's your {beverage.Label}");
}
else
{
Console.WriteLine($"Sorry, no {beverage.Label} for you");
}
}
//or, perhaps, the user chose to exit the app
else if (selection.ToUpper() == "EXIT")
{
Console.WriteLine("Exiting");
break;
}
//finally, if the user didn't enter anything I understand
//let him/her know and then let him/her try again
else
{
Console.WriteLine("Pick a valid selection");
}
}
}
}
Separating out the "concerns" in an application is important. Here, the UI is completely separate from the beverage storage. If you want to add another beverage, just add it to the Dictionary up at the top, and the UI will continue to function with the old beverages and the new beverage you added.
I guess you want this code, If _coke less than 0 show message ,otherwise subtract _coke value.
public int Coke
{
get { return _coke; }
set
{
if (_coke <= 0)
{
Console.WriteLine("No more Coke Left!");
}
else
{
_coke = value;
}
}
}
I have a class that is an entity from a database that has a bunch of dates represented as strings. For example, it could be something like this:
public class Stuff
{
public string Date1 {get;set;}
public string Date2 {get;set;}
public string Date3 {get;set;}
public string Date4 {get;set;}
}
I then have a Validation method that validates other properties and also validates the date properties. Currently, I am validating each date separately for each object. This works, but I was wondering if there was a way I could make it generic so I didn't have to duplicate code across classes and within the class itself. I am currently doing something like:
public bool ValidateDate(string date)
{
string[] overrides = {"","__/__/____"};
bool success = true;
DateTime dateTime;
if(!overrides.Contains(date) && !DateTime.TryParse(date,out dateTime))
{
success = false;
}
return success;
}
//Notice in this method I am repeating the if statements.
public bool Validate(Stuff stuff, out string message)
{
message = string.Empty;
bool success = true;
if(!ValidateDate(stuff.Date1))
{
success = false;
message = "Date 1 is invalid";
}
if(!ValidateDate(stuff.Date2))
{
success = false;
message = "Date 2 is invalid";
}
if(!ValidateDate(stuff.Date3))
{
success = false;
message = "Date 3 is invalid";
}
if(!ValidateDate(stuff.Date4))
{
success = false;
message = "Date 4 is invalid";
}
return success;
}
void Main()
{
string message;
Stuff stuff = new Stuff();
stuff.Date1 = "01/01/2020";
stuff.Date2 = "__/__/____";
stuff.Date3 = "";
stuff.Date4 = "44/__/____";
bool valid = Validate(stuff, out message);
}
I thought about doing something like:
public bool Validate<T>(T value, out string message)
{
//Validation here
}
But, correct me if I am wrong, but this would require that I get the properties and use reflection to check the value of the date and my other problem with this is that the properties are strings, so there is no way for me to check if it is a DateTime?
I feel like I'm missing some information - right now the duplication that I see is that you are calling ValidateDate multiple times. I don't think there is a way around that - you have to call Validate on each Date property, unless (as you mentioned) you want to go the reflection route.
With reflection you would simply iterate through all properties and find any property who's name matches the pattern Date[number], you would then validate that it was indeed a DateTime (with Parse like you already do) and then move on.
If the number of fields is known and isn't too much I'd stick with your ValidateMethod though notice that message will currently only ever show you the last error (it gets overwritten each time).
You could get cute and write a method like:
public bool Validate(Stuff stuff, out string message)
{
message = "Invalid Date(s): ";
return ValidateDates(ref message, stuff.Date1, stuff.Date2, stuff.Date3, stuff.Date4);
}
public bool ValidateDate(ref string message, params string[] dates)
{
bool rv = true;
for (int i = 0; i < dates.Length; i++)
{
if (![validate DateTime as above])
{
message += i + " "; // add the failed index to the message
rv = false;
}
}
return rv;
}
The best you can do is probably something like this, although I don't advocate using string to represent dates.
public bool ValidateDates(params string[] dates)
{
return dates.All( d => ValidateDate(d));
}
public bool Validate(Stuff stuff, out string message)
{
ValidateDates(stuff.Date1,stuff.Date2,stuff.Date3);
}
You can obviously play around with this to know which date failed, for instance you can do something like
var item = dates.Select( d, i => new
{
Valid = ValidateDate(d),
Message = String.Format("Date {0} failed", i)
}).FirstOrDefault( x => !x.Valid);
if(item == null) //everything is valid
return true;
else
//set the out param
outMessageStr = item.Message;
return false;
You could make everything generic by using interfaces for the objects that you want to get dates from.
For instance:
//Defines an interface that provides a function to get multiple dates from an object.
public interface IGetDates
{
//You could use a Read-Only property too
string[] GetDates();
}
public class Stuff : IGetDate
{
//other stuff...
public string[] GetDates()
{
return new[]{ Date1, Date2, Date2, ect...};
}
}
Then your generic method would look like this:
//Uses generic constraints so only objects that use the
//IGetDates interface can call this method.
public bool Validate<T>(T stuff, out string message) where T : IGetDates
{
message = string.Empty;
bool success = true;
string[] dates = stuff.GetDates();
for(int i = 0; i < dates.Length; i++)
{
if(!Validate(dates[i]))
{
success = false;
message = string.Format("Date {0} is invalid.", i);
}
}
return success;
}
I have been writing a check in a name property of my person abstract class. The problem that i have is that i am trying to implement a piece of code that will not allow the user to leave the field empty or to exceed the name limit with 35characters or in-put a digit but i am stuck with it. If any one can help or suggest me.
public string Name
{
get { return name; }
set
{
while (true)
{
if (value == "" || value.Length > 35)
{
Console.Write("Please Enter Correct Name: ");
value = Console.ReadLine();
continue;
}
foreach (char item in value)
{
if (char.IsDigit(item))
{
Console.Write("Digits Are NotAllowed....\n");
Console.Write("Please Enter Correct Name: ");
value = Console.ReadLine();
break;
}
}
break;
}
name = value;
}
}
Don't do any form of UI or I/O in a property.
public string Name
{
get { return _name; }
set
{
if (! Regex.IsMatch(value, #"\w{1-35}"))
throw new ArgumentException("Name must be 1-35 alfanum");
_name = value;
}
}
The exact regular expression is up for discussion but the best practice:
do not try to list and reject all the patterns you don't like. Too much possibilities.
accept what you expect (and understand), reject everything else.
This sort of validation should be broken up. The setter should only know the various restrictions that it has and throw an exception in the case that an invalid value makes it that far. Do not put user interface code in there.
Try something like this:
public string Name
{
get { return name; }
set
{
if (value == "" || value.Length > 35)
{
throw new ArgumentException("Invalid name length.");
}
foreach (char item in value)
{
if (char.IsDigit(item))
{
throw new ArgumentException("Digits are not allowed.");
}
}
name = value;
}
}
Then something like this in your console application:
bool success = false;
while(!success)
{
try
{
Console.WriteLine("Please enter a name:");
myObject.Name = Console.ReadLine();
success = true;
}
catch(ArgumentException ex)
{
Console.WriteLine(ex.Message);
}
}
First of all, never ask for Console input inside of a setter. It is a seriously bad practice. Instead, you should throw an Exception from the setter and let the caller handle that however they need:
public string Name
{
get { return name; }
set
{
if(String.IsNullOrWhiteSpace(value))
throw new ArgumentException("Name must have a value");
if(value.Length > 35)
throw new ArgumentException("Name cannot be longer than 35 characters");
if(value.Any(c => char.IsDigit(c))
throw new ArgumentException("Name cannot contain numbers");
name = value;
}
}
You can then catch and handle the Exceptions appropriately in the calling code (which, in your case, would involve re-prompting the user for the input).
The solution for handling this according to your rules are almost obvious but the thing is, it's better not to put the checking and validating logic in the setter method of a property, you can have a separate class for instance and that class does the validation responsibility for you and you can tell it to do that and then use the result appropriately. In that case you are following "Tell, Don't Ask" rule and also "Single Responsibility Principle"
Good Luck
public string Name
{
get { return name; }
set { name = value; }
}
public static bool IsNameValid(string name)
{
if (string.IsNullOrEmpty(name) || name.Length > 35)
{
return false;
}
foreach (char item in value)
{
if (!char.IsLetter(item))
{
return false;
}
}
return true;
}
Finally a code snippet for reading an user input.
var yourClassInstance = new YourClass();
string input
bool inputRead = false;
while(!inputRead)
{
var input = Console.ReadLine();
inputRead = YourClass.IsNameValid(input);
}
yourClassInstance.Name = inputRead;
The short answer for this is to loop while the value is not valid:
public string GetName()
{
String name = String.Null;
do
{
Console.Write("Please Enter Correct Name: ");
name = Console.ReadLine();
} while (!ValidateName(name))
}
public bool ValidateName(string name)
{
//String validation routine
}
That being said, as I'm sure you will see from other answers, change where the Name is given. As a general rule, accessors are really just for "getting" and "setting" quickly what's in a class.
I would create a method for changing the name that contains the validation logic. If you want to check the name is valid, so you don't have to handle the argumentexception do a check first, call IsValidName before calling ChangeName
public class Person
{
public void ChangeName(string name)
{
if (!IsValidName(name))
{
throw new ArgumentException(....);
}
else
this.Name = value;
}
public bool IsValidName(string name)
{
// is the name valid using
}
public string Name { get; private set; }
}
And to use it
var newName = Console.ReadLine();
var person = new Person();
while (!person.IsValidName(newName))
{
newName = Console.ReadLine();
}
person.ChangeName(newName);
From a semantics point of view, a setter is as its name says, a setter! It should be used to set a private/protected field of a class
From a testability point of view, your design is very hard to be automatically tested not to say impossible!
This reminds me of a bit of code I worked on sometime ago where a setter is opening a socket and sending stuff over the network!
The code should do what it reads, just imagine if someone uses your code, calls your setter and wonders why on earth does his/her application hang (waiting for user input)
The way I see your code more readable and testable is to have a verifer class that ensures the user is entering the right data in the right format. The verifier should take an input stream as data source, this will help you easily test it.
Regards,
Aside from what Mr Skeet said, seems like you should replace this break with a continue in order to validate the new value (like you do in your first length check):
if (char.IsDigit(item))
{
Console.Write("Digits Are NotAllowed....\n");
Console.Write("Please Enter Correct Name: ");
value = Console.ReadLine();
continue; //here
}