Returning string and int from same method - c#

public static int getInfo(string info)
{
string inputValue;
int infor;
Console.WriteLine("Information of the employee: {0}", info);
inputValue = Console.ReadLine();
infor = int.Parse(inputValue);
return infor;
}
In the above code, how can I get the name(string) and salary(int) of a person? Specifications are that I need to call the method twice for the information retrieval.

You can pass it separately or better if you create a class which holds of info and the salary
public static int getInfo(string info,int salary)
or create a class,
public class MyInfo
{
public int info { get; set; }
public int salary { get; set; }
}
and the method signature goes as,
public static int getInfo(MyInfo info)
If you want to return both string and int , better to change the method signature as of type class MyInfo
public static MyInfo getInfo(MyInfo info)

You could make it return a tuple with both values like this:
internal Tuple<int, string> GetBoth(string info)
{
string inputValue;
int infor;
Console.WriteLine("Information of the employee: {0}", info);
inputValue = Console.ReadLine();
infor = int.Parse(inputValue);
return new Tuple<int, string>( infor, inputValue );
}
internal void MethodImCallingItFrom()
{
var result = GetBoth( "something" );
int theInt = result.Item1;
string theString = result.Item2;
}

For returning multiple values from a method we can use Tuples or (DataType, DataType,..).
Tuples are readonly. As a result assigning values is possible only via constructor at the time of declaration.
Below example is using multiple data types as return type. Which is both read and write enabled.
public (string, int) Method()
{
(string, int) employee;
employee.Item1="test";
employee.Item2=40;
return employee;
}
You can call the above method in your main code, as shown below:
static void Main(string[] args)
{
(string name,int age) EmpDetails = new Program().Method();
string empName= EmpDetails.name;
int empAge = EmpDetails.age;
//Not possible with Tuple<string,int>
EmpDetails.name = "New Name";
EmpDetails.age = 41;
}
However, the best practice is to use class with properties, as mentioned in above answers.

public static void Main(string[] args)
{
string eName, totalSales;
double gPay, tots, fed, sec, ret, tdec,thome;
instructions();
eName = getInfo("Name");
totalSales = getInfo("TotalSales");
tots = double.Parse(totalSales);
gPay = totalGpay(tots);
}
public static string getInfo(string info)
{
string inputValue;
Console.WriteLine("Information of the employee: {0}", info);
inputValue = Console.ReadLine();
return inputValue;
}
This is what was required. Could have done with other tricks mentioned by you guys. Anyway thank you.

Why dont you just return a String array with a size of 2? at the first (array[0]) there is the string and at the second (array[0]) there is the int...
public static string[] GetInfo (string info)
I hope I understood your question right ^^

you need to create a person class and read name and salary
public class Person
{
public string Name {get; set;}
public decimal Salary {get; set;}
}
and your function will be:
public static Person getInfo(string info)
{
string inputName;
string inputSalary;
Console.WriteLine("Information of the employee: {0}", info);
Console.WriteLine("Name:");
inputName = Console.ReadLine();
Console.WriteLine("Salary:");
inputSalary = Console.ReadLine();
Person person = new Person();
person.Name = inputName;
person.Salary = int.Parse(inputSalary);
return person;
}

If you want one method to return different types of information, then I would use generics:
public static T GetInfo<T>(string name);
// This can be called as following:
string name = GetInfo<string>("name");
int salary = GetInfo<int>("salary");
There's one problem, though: Console.ReadLine returns a string, while our method could return any type. How can it convert a string to its 'target' type? You could check T and write custom logic for all types you want to support, but that's cumbersome and brittle. A better solution is to let the caller pass in a little function that knows how to transform a string into a specific type:
public static T GetInfo<T>(string name, Func<string, T> convert);
// This can be called as following:
string name = GetInfo<string>("name", s => s);
int salary = GetInfo<int>("salary", int.Parse);
Now how do you implement that method?
public static T GetInfo<T>(string name, Func<string, T> convert)
{
Console.WriteLine("Please enter " + name);
string input = Console.ReadLine();
return convert(input);
}
A few notes:
Type parameters are often just named T, but I find it useful to give them more descriptive names, such as TInfo.
The <string> and <int> parts can be left out in the second example, because the compiler has sufficient information to infer their types.
I've left our error handling to keep the examples short and simple. In production code, you'll want to come up with a strategy to handle invalid input, though.

Related

How to print contents of list instead of type? C# [duplicate]

This question already has answers here:
WriteLine with a class
(9 answers)
Closed 5 years ago.
Probably the title doesn't sound very well for most of you guys (skilled programmers), but I'm on my 3rd week of learning C# fundamentals and I cant figure it out how to solve the next task.
I shall store some temperatures for a bunch of cities, asking a user for a cityName first and then for the actual temp in that city. All this stuff should be saved in a list<> and I shall use Class and Constructor.
When I try to print out the result (using foreach) it prints out the name of my namespace and the name of my class like "Task_5.City"
Whats wrong with my code:
public class City //class
{
public string CityName { get; set; }
public int Temperature { get; set; }
public City(string name, int temp)//konstruktor
{
this.CityName = name;
this.Temperature = temp;
}
}
class Program
{
static void Main(string[] args)
{
var cityList = new List<City>();
Console.WriteLine("What is your city?");
string cityName = Console.ReadLine();
Console.WriteLine("What temperature for this city?");
int temp = Convert.ToInt32(Console.ReadLine());
City myCity = new City(cityName, temp);
cityList.Add(myCity);
foreach (var item in cityList)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
You are passing object to the Console.WriteLine(item) instead of passing the string. Console.WriteLine invokes ToString() method of that object that by default returns namespace+class name. You can override this behavior like next:
public class City //class
{
public string CityName { get; set; }
public int Temperature { get; set; }
public City(string name, int temp)//konstruktor
{
this.CityName = name;
this.Temperature = temp;
}
public override string ToString()
{
return string.Format("{0} {1}", CityName, Temperature);
}
}
Or you can use another overload of WriteLine method:
Console.WriteLine("{0} {1}", item.CityName, item.Temperature);
Change Console.WriteLine(item); to one of the following options, if you simply want to write out the contents of your City object.
Console.WriteLine("City: " + item.CityName + " has a temperature of " + item.Temperature + " degrees.");
or, you can use string.Format if you prefer:
Console.WriteLine(string.Format("City: {0} has a temperature of {1} degrees.", item.CityName, item.Temperature));
The item in cityList is of City type, which means that you have properties for CityName and Temperature.
You should use:
Console.WriteLine(item.CityName + " is at " + item.Temperature + ".");
or something similar.
You are using this overload of WriteLine:
public static void WriteLine(object value)
and this overload call ToString method of parameter to produce its string representation. As mentioned Here the default implementation of ToString returns the fully qualified name of the type.
You can override ToString in your City class to be able use instances of this type where a string is expected like Console.WriteLine
public override string ToString()
{
return CityName + Temperature.ToString();
// return $"{CityName} : {Temperature}"; // Or use C# string interpolation
}
Or directly produce required string and pass that to WriteLine method:
Console.WriteLine($"{item.CityName} : {item.Temperature});
Here you are trying to print the object itself. If you would like to print the CityName and Temperature, inside the foreach you have to print the property.
foreach (var item in cityList)
{
Console.WriteLine(item.CityName);
Console.WriteLine(item.Temperature);
}
But here, you are getting a single city and temperature only and printing it. Why do you need a list in that case?

Why I can't create object instance?

I need add objects to list, but I can't understand how to do it correctly.
Every new object I get from console.
How to fix it?
My try:
namespace ExampleCars
{
public class Car
{
public string name;
public int speed;
public Car(string name, int speed)
{
this.name = name;
this.speed = speed;
}
}
class Program
{
static void Main(string[] args)
{
string name;
int speed, elements;
List<Object> cars = new List<Object>();
elements = Convert.ToInt32(Console.ReadLine());
if (elements > 0)
{
for (int i = 0; i < n; i++)
{
name = Convert.ToString(Console.ReadLine());
speed = Convert.ToInt32(Console.ReadLine());
Car newCar = new Car(name, speed);
cars.Add(newCar);
}
}
foreach (var oneCar in cars)
Console.WriteLine(oneCar);
}
}
}
In console I get this (elements == 1):
ExampleCars.Car
First of all, it would be better to create a List of Cars, instead of list of Objects. So change this:
List<Object> cars = new List<Object>();
To this:
List<Car> cars = new List<Car>();
Also it would be great, if you use properties instead of fields. And finally as the solution for your question, and based on what you need to show in your last Console.Writeline method, you can override the ToString method. Your class should be something like this:
public class Car
{
public string Name { get; set; }
public int Speed { get; set; }
public Car(string name, int speed)
{
Name = name;
Speed = speed;
}
public override string ToString()
{
return $"Name = {Name}, Speed = {Speed} ";
}
}
And if you are using the older versions of C#:
return String.Format("Name = {0}, Speed = {1}", Name, Speed);
The $ is called String Interpolation and is available from C#6+. I have provided an equivalent of it using String.Format that is available in older versions of C#.
when you write your Car object in the console, Car.ToString method call in background.
Object.ToString is the major formatting method in the .NET Framework.
It converts an object to its string representation so that it is
suitable for display. Default implementations of the Object.ToString
method return the fully qualified name of the object's type.
Object.ToString Method
if you want to change default string presentation of your object, you have to override the method.
public class Car
{
public string name;
public int speed;
public Car(string name, int speed)
{
this.name = name;
this.speed = speed;
}
public override string ToString()
{
return $"{name} {speed}";
}
}
Console.WriteLine, is responsible of printing text.
In case of Console.WriteLine(string) is actually returns the string value;
In any other case, it tries to convert the value into a string by invoking the instance object .ToString() method.
Any type in C# inherits from System.Object, and thus, it has the .ToString() method.
By using Inheritance, many types override the actual inherited method and implement their perception of what their value should look like as a string.
This can be easily done, by using method overriding and apply your own logic.
Example taken from MSDN
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return "Person: " + Name + " " + Age;
}
}
Test code
Person person = new Person { Name = "John", Age = 12 };
Console.WriteLine(person);
// Output:
// Person: John 12
So you may ask, why do i get ExampleCars.Car ? you're getting it, because you didn't implement your own representation of the object .ToString method. Thus, the System.Object implementation is to actually return the instance type as string, which is exactly what you're getting.
System.Object.ToString() Source code.
public virtual String ToString()
{
return GetType().ToString();
}
System.Int32 implement by changing the value of 1 to "1"
While other type can implement their own. e.g: new DateTime(2018, 12, 31) can return "12/31/2018"

Error with the command System.IO.File.WriteAllLines()

Hello i am trying to save an object that i have been created and its returning to me error: "represents as a series of Unicode character" on this line: System.IO.File.WriteAllLines(#"C:\Users\1\AppData\Roaming\MYDATA\hi.txt", somOne);
here is the code:
main class:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Persone somOne = new Persone("bob", 5, 200);
System.IO.Directory.CreateDirectory(#"C:\Users\1\AppData\Roaming\MYDATA");
// the Error line Is HERE \/
System.IO.File.WriteAllLines(#"C:\Users\1\AppData\Roaming\MYDATA\hi.txt", somOne);
}
}
}
persone class:
namespace ConsoleApplication1
{
class Persone
{
private String name;
private int id;
private int age;
public Persone(String name, int id, int age)
{
setName(name);
setId(id);
setAge(age);
}
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setId(int id)
{
this.id = id;
}
public int getId()
{
return id;
}
public void setAge(int age)
{
this.age = age;
}
public int getAge()
{
return age;
}
}
}
do i need to chang the type of "somOne"? and how?
System.IO.File.WriteAllLines expects array of strings (or IEnumerable<string>) as second parameter, so code you have should not even compile. You can add to your Person class something like:
public string[] ToStringArray()
{
//And put it everything you need to store
return new[] {name, id.ToString(), age.ToString()};
}
and call like this:
System.IO.File.WriteAllLines(#"C:\Users\1\AppData\Roaming\MYDATA\hi.txt", somOne.ToStringArray());
You can't just save an object like that. They don't automatically format themselves for save to disk.
You want to look into either Serialization or override the .ToString() method for the class and use File.WriteAllText() instead.
According to MSDN, File.WriteAllLines requires an IEnumerable<string> or a string[] as input (the full signature is File.WriteAllLines(string, IEnumberable<string>) or File.WriteAllLines(string, string[]) where the first string is the path and the second is the set of lines you wish to write.
Passing your Persone object is not the same. At the very least you would need to override .ToString() on your object, better might be to write a new method .WritePersone() or something like that.
With the first, you'd call WriteAllLines like this:
System.IO.File.WriteAllLines(#"C:\Users\1\AppData\Roaming\MYDATA\hi.txt",
new string[] {somOne.ToString()});
I hope I'm getting your question correctly.
By this
// the Error line Is HERE \/
System.IO.File.WriteAllLines(#"C:\Users\1\AppData\Roaming\MYDATA\hi.txt", somOne);
you are saying you're getting an error on the above line?
You should've got a compile time error there. The 2nd parameter of WriteAllLines takes either an array or IEnumerable of strings.
Try adding this to your Persone class
public string[] Dump()
{
string[] tmp = new string[3];
tmp[0] = id.ToString();
tmp[1] = name;
tmp[2] = age.ToString();
return tmp;
}
then write to file using
System.IO.File.WriteAllLines(#"C:\Users\1\AppData\Roaming\MYDATA\hi.txt", someone.Dump());

When using WCF, Function Overloading rule?

I use Windows Communication Services (WCF) in my project.
In my project,
I write the function like below:
GetUserNameByUserId(int userId);
GetProductInformationByProductId(int productId);
But this naming have been coming more and more complex day by day.
For instance I have 5 parameters to pass to the function, in this case the function name will be like blow:
GetStackOverFlowByStackByOverByFlowByIdByStackOverFlow(string stack, string over, string flow, int id, string stackOverFlow);
And assume that I want to get with 2 parameters like blow:
GetStackOverFlowByIdByStackOverFlow(int id, string stackOverFlow);
I want to use function overloading like below:
public void abc(int i)
{
System.Console.WriteLine("abc" + i);
}
public void abc(string i)
{
System.Console.WriteLine("abc" + i);
}
public void abc(string i,int j)
{
System.Console.WriteLine("abc" + i + j);
}
That is to say, I want to write below functions:
GetStackOverFlow(int id);
GetStackOverFlow(int id, string name);
GetStackOverFlow(int id, string name, string StackOver);
.
.
Isn't it?
Are there any methodology for that?
Or am I doing right?
I research and find this:
Function Overloading in WCF
public interface IMyService
{
[OperationContract(Name = "GetStringWithParam")]
string GetString(DateTime date);
[OperationContract(Name = "GetStringWithoutParam")]
string GetString();
}
and he said that
But i don't prefer it as it is sometimes lead to confusion.
are there any other way?
Thanks.
You could use a class as a parameter.
[DataContract]
public class MySearchSettings
{
[DataMember]
public int? ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string StackOver { get; set; }
}
and than create a method like this:
public GetStackOverflowResponse GetStackOverflow(MySearchSettings searchSettings)
{
var response = new GetStackOverflowResponse();
try
{
User user = null;
if (searchSettings == null)
throw new ArgumentNullException("searchSettings");
if (searchSettings.ID.HasValue)
user = //queryByID;
else if (!String.IsNullOrEmpty(searchSettings.Name))
user = //queryByName;
else if (!String.IsNullOrEmpty(searchSettings.StackOver))
user = //queryByStackOver;
response.User = user;
}
catch(Exception e)
{
response.ErrorMessage = String.Format("{0}: {1}",
e.GetType().Name,
e.Message);
}
return response;
}
I have not included the GetStackOverflowResponse class but you get the idea of it.
One of the benefits of this is that you could easily extend the class without breaking functionality of a client when a newer version of your Service is deployed.
You are doing fine and this is how you overload methods in WCF(using the name property).I dont see a better approach than using the name property to overload methods.

Reflection in C#

I have recently started a development in c# and want to use reflection in following situation.
If I have a Enum class as
Enum Operation
{
Read=0;
Write;
}
If I give input as
String str = "Operation.Write";
I shoud be able to get output as 1;
Or
if constants are defined like
const int Read=0;
const int Write=1;
If the input is
String str = "Read";
output should be 0
Please Help.
You can use Enum.Parse to have that functionality.
If we combine your proposals we can get something like this.
public static Operation getOperationByName(String name) {
return Enum.Parse(typeof(Operation),name);
}
Where the name should not be null and represent the name or position in enum ie
"Read" will return Operation.Rerad and "1" will return Operation.Write
Heres the complete code to also Get the type of the Enum through Reflection without hardcoding it. The ParseConstant Method is also generic, s.t. you can use if for every Type.
namespace MyNamgespace
{
public enum Operation
{
Read = 0,
Write
}
public class ClassWithConstants
{
public const int Read = 0;
public const int Write = 1;
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine((ParseEnum("Operation.Write")));
Console.WriteLine((ParseContant<ClassWithConstants>("Write")));
Console.ReadLine();
}
static int ParseEnum(string enumValue)
{
var typeName = enumValue.Split('.')[0];
var valueName = enumValue.Split('.')[1];
var enumType = Type.GetType(string.Format("MyNamespace.{0}", typeName));
var op = (Operation) Enum.Parse(enumType, valueName);
return (int)op;
}
static int ParseContant<T>(string constantName)
{
var type = typeof (T);
var field = type.GetField(constantName, BindingFlags.Static | BindingFlags.Public);
return (int)field.GetValue(null);
}
}
}
var name = Enum.GetName(typeof(Operation), Operation.Write) //name = 'Write'
var value = Enum.Parse(typeof(Operation), "Write") //value = Operation.Write

Categories