Assign value when calling method Syntax in C# - c#

I am sorry I don't know if C# has this syntax or not and I don't know the syntax name. My code below, I want to add 2 people has the same name but not age. So I am wondering if C# has a brief syntax that I can change the Age property value when calling AddPerson method. Please tell me if I can do that? If can, how can I do? Thank you.
class Program
{
static void Main(string[] args)
{
//I want to do this
Person p = new Person
{
Name = "Name1",
//And other propeties
};
AddPerson(p{ Age = 20});
AddPerson(p{ Age = 25}); //Just change Age; same Name and others properties
//Not like this(I am doing)
p.Age = 20;
AddPerson(p);
p.Age = 25;
AddPerson(p);
//Or not like this
AddPerson(new Person() { Name = "Name1", Age = 20 });
AddPerson(new Person() { Name = "Name1", Age = 25 });
}
static void AddPerson(Person p)
{
//Add person
}
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
//And more
}

If Person is a Record-Type, then yes: by using C# 9.0's new with operator. Note that this requires C# 9.0, also note that Record-Types are immutable.
public record Person( String Name, Int32 Age );
public static void Main()
{
Person p = new Person( "Name1", 20 );
List<Person> people = new List<Person>();
people.Add( p with { Age = 25 } );
people.Add( p with { Age = 30 } );
people.Add( p with { Name = "Name2" } );
}
This is what I see in LinqPad when I run it:

Related

Build Dynamic query using Expression Tree

I am working on dynamic query building in LINQ using Expression Tree.
I have taken the reference to the following post
https://www.codeproject.com/Tips/582450/Build-Where-Clause-Dynamically-in-Linq
How can I build expression if I want to check all the element in the list contains in another collection or not?
I have a Person class
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
and I have a list
List<Person> personList = new List<Person>()
{
new Person{ Name = "Shekhar", Age = 31},
new Person{ Name = "Sandip", Age = 32},
new Person{ Name = "Pramod", Age = 32},
new Person{ Name = "Kunal", Age = 33}
};
I have another list
List<string> nameList = new List<string>() { "Sandip", "Prashant" };
How can I build expression tree to check all the element in the list "nameList" contains in "personList" and give result true or false?
try this:
public bool Find(List<string> nameList, List<Person> personList)
{
foreach (var name in nameList)
if (personList.FirstOrDefault(person => person.Name == name) != null)
{
// Find
return true;
}
return false;
}
try this:
bool contained = !personList.Select(l=>l.Name).Except(nameList).Any();

LINQ to Get All heirerichal children

I have been digging this quite a while.
public class Person
{
public string Name { get; set; }
public string Age { get; set; }
public List<Person> Children { get; set; }
}
I want a single LINQ query to find out "All the persons whose Age > 4 in this collection".
Note: You have to traverse Collection of Person + Collection of Children, so each children object will have a collection of Person till Children becomes null.
First i can't understand why all your properties private and Age is not int type. So my class looks like this:
public partial class Person
{
public string Name { get; set; }
public int Age { get; set; }
public List<Person> Childrens { get; set; }
}
Note partial word. This word will allow you to place your class logic in separate files and this could be usefull when you creating some custom logic in class.
Then I simply create this method in different file:
public partial class Person
{
public Person GetPersonWithChindren(int maxAge)
{
return new Person
{
Age = this.Age,
Name = this.Name,
Childrens = this.Childrens != null
? this.Childrens
.Where(x => x.Age < maxAge)
.Select(x => x.GetPersonWithChindren(maxAge)) //this line do recursive magic
.ToList()
: null
};
}
}
As you can see this method checking Age of each child and if Age is ok then it checks next level of hierarchy untill Childrens is null.
So you can use it like this:
var person = new Person()
{
//initialisation of your collection here
}
//result will contains only nodes where Person have age < 4 and Childs that have age < 4
var result = person.GetPersonWithChindren(4);
Note that this solution will work normal with linqToEntities. But if you using LinqToSQL this expression produces query to DB on each Person entity. So if you have many Persons and deep hierarhy it will costs you a lot of machine time. In that case you should to write stored procedure with CTE instead of LinQ query.
UPDATE:
You even can write more general solution with a help of Func<T> class like this:
public partial class Person
{
public Person GetPersonWithChindren(Func<Person, bool> func)
{
return new Person
{
Age = this.Age,
Name = this.Name,
Childrens = this.Childrens != null
? this.Childrens
.Where(x => func(x))
.Select(x => x.GetPersonWithChindren(func))
.ToList()
: null
};
}
}
And then you can use it like this:
var result = person.GetPersonWithChindren(x => x.Age < 4);
You always can change your criteria now where you want to use your function.
Create a visitor. In this example by implementing a helper class:
public static class Helpers
public static IEnumerable<Person> GetDescendants(this Person person)
{
foreach (var child in person.Children)
{
yield return child;
foreach (var descendant in child.GetDescendants())
{
yield return descendant;
}
}
}
this is one of the times where the "yield return many" would be useful.
If you're ensuring that .Children is automatically created, then this works:
Func<Person, Func<Person, bool>, Person> clone = null;
clone = (p, f) => f(p) ? new Person()
{
Name = p.Name,
Age = p.Age,
Children = p.Children.Select(c => clone(c, f)).Where(x => x != null).ToList(),
} : null;
var olderThan4 = clone(person, p => p.Age > 4);
Yes, that's it. Effectively three lines.
If you start with this data:
var person = new Person()
{
Name = "Fred", Age = 30,
Children = new List<Person>()
{
new Person() { Name = "Bob", Age = 7, },
new Person() { Name = "Sally", Age = 3, }
},
};
...then you get this result:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
private List<Person> _children = null;
public List<Person> Children
{
get
{
if (_children == null)
{
_children = new List<Person>();
}
return _children;
}
set
{
_children = value;
}
}
}

How to not serialize an object based on a property's value?

If the tags didn't give it away, I'm working with C#'s XmlSerializer class.
Say, for example, I have a Person class with various properties including age (int), name (string), and deceased (bool). Is there a way to specify that I don't want to serialize any objects whose deceased flags are true?
Edit: I should have specified, but unfortunately due to the situation I can't really edit my list of objects because it's a member of another class, which is what I'm actually serializing. Are there any other suggestions?
Assuming that you have following type of Class structure(As you specified in the comment)
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
public bool Deceased { get; set; }
}
public class Being
{
public string Data { get; set; }
[XmlElement("Human")]
public Person Human { get; set; }
public bool ShouldSerializeHuman()
{
return !this.Human.Deceased;
}
}
Here I have added a method called ShouldSerialize this is called a pattern for XML serialization. Here you can use XmlArray and XmlArrayItem for lists etc.(With given name) then the ShouldSerialize checks if it can be serialized.
Below is the code I used for testing.
private static void Main(string[] args)
{
var livingHuman = new Person() { Age = 1, Name = "John Doe", Deceased = true };
var deadHuman = new Person() { Age = 1, Name = "John Doe", Deceased = false };
XmlSerializer serializer = new XmlSerializer(typeof(Being));
serializer.Serialize(Console.Out, new Being { Human = livingHuman, Data = "new" });
serializer.Serialize(Console.Out, new Being { Human = deadHuman, Data = "old" });
}
And here's the output:
=============================
Update:
If you have list of Person as Humans:
public class Being
{
// [XmlAttribute]
public string Data { get; set; }
// Here add the following attributes to the property
[XmlArray("Humans")]
[XmlArrayItem("Human")]
public List<Person> Humans { get; set; }
public bool ShouldSerializeHumans()
{
this.Humans = this.Humans.Where(x => !x.Deceased).ToList();
return true;
}
}
Sample Test:
private static void Main(string[] args)
{
var livingHuman = new Person() { Age = 1, Name = "John Doe", Deceased = true };
var deadHuman = new Person() { Age = 1, Name = "John Doe", Deceased = false };
var humans = new List<Person> { livingHuman, deadHuman };
XmlSerializer serializer = new XmlSerializer(typeof(Being));
serializer.Serialize(Console.Out, new Being() { Humans = humans, Data = "some other data" });
}
Output:
If you have a list of Person objects and only want to serialise some of them, then just filter out the ones you don't need. For example:
List<Person> people = GetPeople(); //from somewhere
List<Person> filteredPeople = people.Where(p => !p.Deceased);
Now you only need to serialise filteredPeople.

c# : how to read from specific index in List<person>

I have a class of persons and list collection as list contains all the values of person class
such as :
List ilist has 2 values [0]={firstname,lastname} . [1]={firstname2,lastname2}
now when i am iterating into the list i am able to print the list but i want to change the value of some parts of my list e.g in index 1 if i want to change the value of firstname2 to firstname3 i am not able to do it . Can anyone tell me how to print the list and then on that index changing any value of the index , i.e. firstname and secondname variable in the person class so that i can update my values
Thanks
According to the docs on msdn you can use the familiar index operator (like on what you use on arrays). So myList[1].lastname = "new last name"; should do it for you.
Docs are here; http://msdn.microsoft.com/en-us/library/0ebtbkkc.aspx
Keep in mind you need to do bounds checking before access.
I came here whilst searching for access specific index in object array values C# on Google but instead came to this very confusing question. Now, for those that are looking for a similar solution (get a particular field of an object IList that contains arrays within it as well). Pretty much similar to what the OP explained in his question, you have IList person and person contains firstname, lastname, cell etc and you want to get the firstname of person 1. Here is how you can do it.
Assume we have
IList<object> myMainList = new List<object>();
myMainList.Add(new object[] { 1, "Person 1", "Last Name 1" });
myMainList.Add(new object[] { 2, "Person 2", "Last Name 2" });
At first, I though this would do the trick:
foreach (object person in myMainList)
{
string firstname = person[1].ToString() //trying to access index 1 - looks right at first doesn't it??
}
But surprise surprise, C# compiler complains about it
Cannot apply indexing with [] to an expression of type 'object'
Rookie mistake, but I was banging my head against the wall for a bit. Here is the proper code
foreach (object[] person in myMainList) //cast object[] NOT object
{
string firstname = person[1].ToString() //voila!! we have lift off :)
}
This is for any newbie like me that gets stuck using the same mistake. It happens to the best of us.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
List<Person> list = new List<Person>();
Person oPerson = new Person();
oPerson.Name = "Anshu";
oPerson.Age = 23;
oPerson.Address = " ballia";
list.Add(oPerson);
oPerson = new Person();
oPerson.Name = "Juhi";
oPerson.Age = 23;
oPerson.Address = "Delhi";
list.Add(oPerson);
oPerson = new Person();
oPerson.Name = "Sandeep";
oPerson.Age = 24;
oPerson.Address = " Delhi";
list.Add(oPerson);
int index = 1; // use for getting index basis value
for (int i=0; i<list.Count;i++)
{
Person values = list[i];
if (index == i)
{
Console.WriteLine(values.Name);
Console.WriteLine(values.Age);
Console.WriteLine(values.Address);
break;
}
}
Console.ReadKey();
}
}
class Person
{
string _name;
int _age;
string _address;
public String Name
{
get
{
return _name;
}
set
{
this._name = value;
}
}
public int Age
{
get
{
return _age;
}
set
{
this._age = value;
}
}
public String Address
{
get
{
return _address;
}
set
{
this._address = value;
}
}
}
}
More information on your requirement / why you are accessing the list this way might help provide a better recommendation on approach but:
If you want to use your list in this way frequently an Array or ArrayList may be a better option.
That said, if your specific issue is determining the current element you want to change's ID you can use IndexOf(). (note this will loop the array to find the object's position)
If you just know the index of the element, you can reference as both you and #evanmcdonnal describe.
Lists can be modified directly using their indexer.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
var list = new List<Person>
{
new Person
{
FirstName = "Bob",
LastName = "Carlson"
},
new Person
{
FirstName = "Elizabeth",
LastName = "Carlson"
},
};
// Directly
list[1].FirstName = "Liz";
// In a loop
foreach(var person in list)
{
if(person.FirstName == "Liz")
{
person.FirstName = "Lizzy";
}
}
I do not see where you can meet the problem:
public class Persons
{
public Persons(string first, string last)
{
this.firstName = first;
this.lastName = last;
}
public string firstName { set; get; }
public string lastName { set; get; }
}
...
List<Persons> lst = new List<Persons>();
lst.Add(new Persons("firstname", "lastname"));
lst.Add(new Persons("firstname2", "lastname2"));
for (int i = 0; i < lst.Count; i++)
{
Console.Write("{0}: {2}, {1}", i, lst[i].firstName, lst[i].lastName);
if (i == 1)
{
lst[i].firstName = "firstname3";
lst[i].lastName = "lastname3";
Console.Write(" --> {1}, {0}", lst[i].firstName, lst[i].lastName);
}
Console.WriteLine();
}
}
Output:
0: lastname, firstname
1: lastname2, firstname2 --> lastname3, firstname3

What am I doing wrong with C# object initializers?

When i initialize an object using the new object initializers in C# I cannot use one of the properties within the class to perform a further action and I do not know why.
My example code:
Person person = new Person { Name = "David", Age = "29" };
Within the Person Class, x will equal 0 (default):
public Person()
{
int x = Age; // x remains 0 - edit age should be Age. This was a typo
}
However person.Age does equal 29. I am sure this is normal, but I would like to understand why.
The properties get set for Name and Age after the constructor 'public Person()' has finished running.
Person person = new Person { Name = "David", Age = "29" };
is equivalent to
Person tempPerson = new Person()
tempPerson.Name = "David";
tempPerson.Age = "29";
Person person = tempPerson;
So, in the constructor Age won't have become 29 yet.
(tempPerson is a unique variable name you don't see in your code that won't clash with other Person instances constructed in this way. tempPerson is necessary to avoid multi-threading issues; its use ensures that the new object doesn't become available to any other thread until after the constructor has been executed and after all of the properties have been initialized.)
If you want to be able to manipulate the Age property in the constructor, then I suggest you create a constructor that takes the age as an argument:
public Person(string name, int age)
{
Name = name;
Age = age;
// Now do something with Age
int x = Age;
// ...
}
Note, as an important technical detail, that:
Person person = new Person { Name = "David", Age = "29" };
is equivalent to:
Person <>0 = new Person(); // a local variable which is not visible within C#
<>0.Name = "David";
<>0.Age = "29";
Person person = <>0;
but is not equivalent to:
Person person = new Person();
person.Name = "David";
person.Age = "29";
Your line of code is identical to:
Person person = new Person() { Name = "David", Age = "29" };
which is identical to:
Person person = new Person();
person.Name = "David";
person.Age = "29";
As you can see; when the constructor executes, Age is not yet set.
Technically, this code:
Person person = new Person { Name = "David", Age = 29 };
is identical to this code:
Person tmpPerson = new Person();
tmpPerson.Name = "David";
tmpPerson.Age = 29;
Person person = tmpPerson;
which is slightly different than what others have posted:
Person person = new Person();
person.Name = "David";
person.Age = 29;
This difference is crucial if your application is using multi-threading.
It looks like you're trying to access Age in the object's constructor. The object initializer values won't be set until after the constructor has executed.
Try this:
Person person = new Person { Name = "David", Age = 29 };
int x = person.Age;
EDIT in response to comment
If you need access to Age in the constructor itself then you'll need to create an explicit constructor with the required parameters, and use that instead of the object initializer syntax. For example:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
int x = Age; // will be 29 in this example
}
}
Person person = new Person("David", 29);
Well, as others said, the parameterless constructor got executed first, hence your quandary.
I do have to ask however, if you've set a field instead of an automatic property for your Age variable?
public class Person
{
private int _age;
public int Age
{
get { return _age; }
set { _age = value; }
}
}
You could use _age instead of x if that's enough, or if you really need to use x:
public class Person
{
private int _age;
private int x;
public int Age
{
get { return _age; }
set
{
_age = value;
x = _age;
}
}
}
Whichever is more appropriate.

Categories