So I have a class:
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public Person()
{
AddPerson();
}
private void AddPerson()
{
string fn = this.Firstname;
string ln = this.Lastname;
// Do something with these values
// Probably involves adding to a database
}
}
And I have some code that will instantiate an object and add it to the database, returning the the object of type Person:
Person me = new Person()
{
Firstname = "Piers",
Lastname = "Karsenbarg"
};
However, when I debug this, and get to the AddPerson() method, the properties this.Firstname and this.Lastname don't have anything in them (in this case are empty).
Where am I going wrong?
This is because properties are assigned after constructor is called. Basicaly, this:
Person me = new Person()
{
Firstname = "Piers",
Lastname = "Karsenbarg"
};
is the same as:
Person me = new Person();
me.Firstname = "Piers";
me.Lastname = "Karsenbarg";
Only difference here is syntax. In your case you may want to pass those variables via parametrized constructor (new Person("Piers", "Karsenbarg")).
You have not assigned any values to your properties. I would suggest passing in the names you want in the constructor:
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public Person(string firstname, lastname)
{
this.Firstname = firstname;
this.Lastname = lastname;
AddPerson();
}
private void AddPerson()
{
string fn = this.Firstname;
string ln = this.Lastname;
// Do something with these values
// Probably involves adding to a database
}
}
A person cannot exist without a firstname or lastname so this makes logical sense
Related
Lets say I have a simple class
public class Person {
string firstName;
string lastName;
int age;
.... additional properties
}
then I have some code that does say
person = new Person("bob", "Smith", 27);
Is there a way (maybe with Linq?) I can get a string returned that is
"firstName Bob /n lastName Smith /n age 27"
Yes, try this:
void Main()
{
var person = new Person("bob", "Smith", 27);
var result = String.Join(Environment.NewLine, typeof(Person).GetFields().Select(p => $"{p.Name} {p.GetValue(person)}"));
Console.WriteLine(result);
}
public class Person
{
public Person(string firstName, string lastName, int age)
{
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public string firstName;
public string lastName;
public int age;
}
That gives:
firstName bob
lastName Smith
age 27
If you have control of the Person class then this is the more idiomatic way to tackle this:
void Main()
{
var person = new Person("bob", "Smith", 27);
var result = person.ToString();
Console.WriteLine(result);
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public Person(string firstName, string lastName, int age)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Age = age;
}
public override string ToString()
{
return String.Format("FirstName {0}\nLastName {1}\nAge {2}", FirstName, LastName, Age);
}
}
If you are just trying to save coding the ToString by hand then you could certainly do a combination of both methods.
Each class comes with a default implementation of ToString(). You can override this default implementation with whatever you fancy. For your case you can try something like this:
public class Person
{
public Person(string firstName, string lastName, int age)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Age = age;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public override string ToString() => $"FirstName {FirstName}{Environment.NewLine}LastName {LastName}{Environment.NewLine}Age {Age}";
}
Then you call ToString() on your instance:
Person person = new Person("Miles", "Morales", 18);
Console.WriteLine(person.ToString());
And this will print out:
FirstName Miles
LastName Morales
Age 18
Pure LINQ is meant for sequences. The input is a sequence (IEnumerable / IQueryable), the output is another sequence for intermediate results (results of Select, GroupBy, Join, ...), or the final result of a LINQ statement (ToList, ToDicationary, Max, Aggregate, Count).
However, you could write your functions in a way that it looks like LINQ: you write them in a format as if your extend class Person with a new method. See Extension Methods demystified
Convert person to a text representation:
static string ToText(this Person person)
{
return $"FirstName {person.firstName}/nLastName {person.lastName}/nAge {person.Age}";
}
Usage:
Person person = ...
string txt = person.ToText();
If you want to use it with sequences of Persons:
static IEnumerable<Person> ToText(this IEnumerable<Person> persons)
{
return persons.Select(person => person.ToText();
}
Usage:
IEnumerable<Person> persons = ...
var result = persons.ToText();
static
I am attemping to read a text file in the format of
(The # at end is just the number of classes they're in, but I dont save the course name with the fac/students class)
Course Biology
Faculty Taylor Nate 0
Student Doe John 3
Student Sean Big 0
Course Art
Faculty Leasure Dan 1
The first input should be a course, followed by the faculty and students of the specific course. The Course class should contain a collection of faculty members and a collection of students.
I have been able to put each course/student/faculty into their respective class, but I am having trouble visualizing a way to add the students/faculty to the course.
My current idea putting the data into their respective classes would be to keep the current index of the course- therefore I have it saved as
courses[currentCourse++]
so when I parse the next line, (being a faculty/student) I already know what the course index should be.
using (StreamReader reader = new StreamReader(fileName))
{
while (!reader.EndOfStream)
{
lineCounter++;
line = reader.ReadLine();
string[] words = line.Split(' ');
Console.WriteLine(words[0]);
if (words[0] == "Course")
{
string nameOfCourse = words[1];
courses[currentCourse++] = new Course
{
Name = nameOfCourse
};
}
if (words[0] == "Faculty")
{
string firstName = words[1];
string lastName = words[2];
string numOfClasses = words[3];
faculty[currentFaculty++] = new Faculty
{
FirstName = firstName,
LastName = lastName,
NumOfClasses = numOfClasses,
};
}
if (words[0] == "Student")
{
string firstName = words[1];
string lastName = words[2];
string numOfClasses = words[3];
students[currentStudent++] = new Student
{
FirstName = firstName,
LastName = lastName,
NumOfClasses = numOfClasses,
};
}
I know the problem lies in the courses class itself- but i'm not sure the terminology to add a class to another class.
public class Course
{
public override string ToString()
{
return $"{Name}";
}
public string Name { get; set; }
}
public class Student
{
public override string ToString()
{
return $"{FirstName} {LastName} {NumOfClasses}";
}
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string NumOfClasses { get; set; } = string.Empty;
}
Thanks for reading!
You want to add a collection of Student and Faculty to the course class, correct? You can do so like this by simply adding a List<T> to your Course class and then initializing it in a constructor.
public class Course
{
public override string ToString()
{
return $"{Name}";
}
public string Name { get; set; }
public List<Student> Students { get; set; }
public List<Faculty> FacultyMems { get; set; }
public Course()
{
Students = new List<Student>();
FacultyMems = new List<Faculty>();
}
}
And in your using block, you can add each student/faculty to the course as so:
if (words[0] == "Course")
{
string nameOfCourse = words[1];
currentCourse++;
courses[currentCourse] = new Course
{
Name = nameOfCourse
};
}
if (words[0] == "Faculty")
{
string firstName = words[1];
string lastName = words[2];
string numOfClasses = words[3];
courses[currentCourse].FacultyMems.Add(new Faculty
{
FirstName = firstName,
LastName = lastName,
NumOfClasses = numOfClasses,
});
}
if (words[0] == "Student")
{
string firstName = words[1];
string lastName = words[2];
string numOfClasses = words[3];
courses[currentCourse].Students.Add(new Student
{
FirstName = firstName,
LastName = lastName,
NumOfClasses = numOfClasses,
});
}
With this, each time you encounter "Course" your course list will add a new item and then you can append students/faculty/etc when those values occur.
This can be simplified even further but the concept is there for you to follow. Hope this helps.
If I'm understanding you correctly, you want your courses to have a list of faculty and students?
public class Course
{
public override string ToString()
{
return $"{Name}";
}
public string Name { get; set; }
public List<Student> Students { get; set; }
public List<Faculty> FacultyMembers {get; set;}
}
Just be sure to initialize the Lists before trying to add things to them otherwise you'll get a null ref exception.
I do a post with an anonymous type on an WebApi controller in the body I have this new { Firstname = "AA", Lastname = "BB"}
[HttpPost]
public IHttpActionResult Post([FromBody]dynamic person)
{
}
When I hit the controller, person is not null and I can see the the properties with their data.
In the controller I'd like convert the dynamic type to my concrete type Person
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
}
I tried with Mapper.Initialize(cfg => cfg.CreateMap<dynamic, Person>());
When I do this
var person = Mapper.Map<dynamic, Person>(source);
All the properties of person are null.
Any idea ?
Thanks,
According to the documentation, instead of...
var person = Mapper.Map<dynamic, Person>(source);
...just use...
var person = Mapper.Map<Person>(source);
Full example:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString() { return FirstName + " " + LastName; }
}
//Main
Mapper.Initialize( cfg => {} );
dynamic source = new ExpandoObject();
source.FirstName = "Hello";
source.LastName = "World";
var person = Mapper.Map<Person>(source);
Console.WriteLine("GetType()= '{0}' ToString()= '{1}'", person.GetType().Name, person);
Output:
GetType()= 'Person' ToString()= 'Hello World'
Link to DotNetFiddle demo
I'm making a simple registration application and I have an assignment to learn more about lists. I have an assignment that says that i am to create a class called Persons and in that class set the values from the text fields in variables and add this to a list of type Person.
So far:
In the Person class:
string strSocialSecurityNumber = string.Empty;//---( This will not be used now.)
string strFirstName = string.Empty;
string strLastName = string.Empty;
string strFullName = string.Empty;
string strAge = string.Empty;
string strAll = string.Empty;
int intAge = 0;
List<Person> lstPerson = new List<Person>();
public void SetValues(string FirstName, string LastName, int Age)
{
strFirstName = FirstName;
strLastName = LastName;
strFullName = strFirstName + " " + strLastName;
intAge = Age;
strAge = Convert.ToString(intAge);
strAll = strAge + " " + strFullName;
}
public List<Person> Person()
{
lstPerson.Add(strAll);
return lstPerson;
}
Error message:
"can not convert from string to Person"
The assignment says that the list is to be of the type Person so I am supposed to add strings to it. I've looked how to do this but I don't know how. I have seen that there are options like "ConvertAll" But I'm not sure if I am allowed to use it since the list should be of type Person.
Both having a list of Person and all the properties in the Person class i a little confusing.
I think the teacher meant that you should create a Persons class containing a list of Person.
public class Person
{
public string strFirstName;
...
}
public class Persons
{
List<Person> lstPersons = new List<Person>();
public void AddPerson(string FirstName, ...)
{
Person person = new Person();
person.strFirstName = FirstName;
...
lstPersons.Add(person);
}
}
I believe that this is more like what the assignment is requesting.
You can not convert string to person
you must use this
public List<Person> Person()
{
lstPerson.Add(new Person(){strAge =yourvalue,...});
return lstPerson;
}
I have the code below. I'd like to convert all items in this list to uppercase.
Is there a way to do this in Linq ?
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public class MyClass
{
List<Person> myList = new List<Person>{
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
}
Update
I don't want to loop or go field by field. Is there a way by reflection to uppercase the value for each property?
Why would you like to use LINQ?
Use List<T>.ForEach:
myList.ForEach(z =>
{
z.FirstName = z.FirstName.ToUpper();
z.LastName = z.LastName.ToUpper();
});
EDIT: no idea why you want to do this by reflection (I wouldn't do this personally...), but here's some code that'll uppercase all properties that return a string. Do note that it's far from being perfect, but it's a base for you in case you really want to use reflection...:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
public static class MyHelper
{
public static void UppercaseClassFields<T>(T theInstance)
{
if (theInstance == null)
{
throw new ArgumentNullException();
}
foreach (var property in theInstance.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
var theValue = property.GetValue(theInstance, null);
if (theValue is string)
{
property.SetValue(theInstance, ((string)theValue).ToUpper(), null);
}
}
}
public static void UppercaseClassFields<T>(IEnumerable<T> theInstance)
{
if (theInstance == null)
{
throw new ArgumentNullException();
}
foreach (var theItem in theInstance)
{
UppercaseClassFields(theItem);
}
}
}
public class Program
{
private static void Main(string[] args)
{
List<Person> myList = new List<Person>{
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
MyHelper.UppercaseClassFields<Person>(myList);
Console.ReadLine();
}
}
LINQ does not provide any facilities to update underlying data. Using LINQ, you can create a new list from an existing one:
// I would say this is overkill since creates a new object instances and
// does ToList()
var updatedItems = myList.Select(p => new Person
{
FirstName = p.FirstName.ToUpper(),
LastName = p.LastName.ToUpper(),
Age = p.Age
})
.ToList();
If using LINQ is not principal, I would suggest using a foreach loop.
UPDATE:
Why you need such solution? Only one way of doing this in generic manner - reflection.
the Easiest approach will be to use ConvertAll:
myList = myList.ConvertAll(d => d.ToUpper());
Not too much different than ForEach loops the original list whereas ConvertAll creates a new one which you need to reassign.
var people = new List<Person> {
new Person { FirstName = "Aaa", LastName = "BBB", Age = 2 },
new Person{ FirstName = "Deé", LastName = "ève", Age = 3 }
};
people = people.ConvertAll(m => new Person
{
FirstName = m.FirstName?.ToUpper(),
LastName = m.LastName?.ToUpper(),
Age = m.Age
});
to answer your update
I don't want to loop or go field by field. Is there a way by
reflection to uppercase the value for each property?
if you don't want to loop or go field by field.
you could use property on the class to give you the Uppercase like so
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string FirstNameUpperCase => FirstName.ToUpper();
public string LastNameUpperCase => LastName.ToUpper();
}
or you could use back field like so
public class Person
{
private string _firstName;
public string FirstName {
get => _firstName.ToUpper();
set => _firstName = value;
}
private string _lastName;
public string LastName {
get => _lastName.ToUpper();
set => _lastName = value;
}
public int Age { get; set; }
}
You can only really use linq to provide a list of new objects
var upperList = myList.Select(p=> new Person {
FirstName = (p.FirstName == null) ? null : p.FirstName.ToUpper(),
LastName = (p.LastName == null) ? null : p.LastName.ToUpper(),
Age = p.Age
}).ToList();
p.lastname.ToString().ToUpper().Contains(TextString)