I was folowing the tutorial at youtube. At 8:04 instructor attached the local method to overloaded ToString, when I try to do same I don't see the overloaded method in intellisense.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime StartDate { get; set; }
public int Rating { get; set; }
public override string ToString()
{
return string.Format("{0} {1}", FirstName, LastName);
}
public string ToString(PersonFormat format)
{
return format(this);
}
I tried adding the keyword override too it does not work.Looks like I am missing something somewhere.
This is because var is hiding the actual type of the person which is object when accessed through PersonListBox.Items. The below works:
foreach(Person person in PersonListBox.Items)
{
}
While :
foreach(var person in PersonListBox.Items)
{
// person is object. It doesn't have the method you want to call.
// it even doesn't have FirstName or LastName
// try person. and you can clearly see it only has the common
// object methods.
}
Hint: you can also use foreach(var p in PersonListBox.Items.OfType<Person>())
Related
I need your help. I've got the following situation that I have a method with has to determine some conditions and depending on these conditions, returning an object of a specific type.
Now, I do not want to say public object methodXY() with object as return type but I have the approach which does not seem to work yet.
public T methodXY<T>()
{
if (condition A)
return (T)Convert.ChangeType(myValue, typeof(myType));
else if (condition B)
return (T)Convert.ChangeType(myValue, typeof(myOtherType));
else
throw new exception("xyz")
}
But with this, it seems that I have to set the return type already when calling the method. That's what I don't want and don't can.
//myType looks like this
public class myType
{
public string name;
public string firstname;
public string address;
}
and
//myOtherType looks like
public class myOtherType
{
public string name;
public string firstname;
}
Do you need more or more detailed information? Let me know.
Thanks in advance :-)
EDIT:
Here is the complete code sample of the method with object
public object myMethod(MyDto myDto)
{
userHasRoles = GetUserRoles();
if (userHasRoles .Contains("Admin"))
return (mapper.Map<myType>(myDto));
else if (userHasRoles.Contains("User"))
return (mapper.Map<myOtherType>(myDto));
throw new Exception("No elements!");
}
As far as I understand the problem, you need to return a more complete data when the retriever is the admin, and a not-so-complete one when not.
If that is the objective, then you can retrieve the appropriate data from the database and fill in an object of one of the following classes:
public class PersonData {
public string Name { get; private set; }
public string Surname { get; private set; }
}
public class ExtendedPersonData: PersonData {
public string Name { get; private set; }
public string Surname { get; private set; }
public string Address { get; private set; }
}
Since the latter class inherits from the former, you can just create a List<PersonData> and that will cover both cases.
Another, different approach: the data class takes into account the user in order to return or not certain data:
class Person {
public Person(User usr, string address)
{
this.User = usr;
this.address = address;
}
public string User { get; private set; }
public string Name { get; private set; }
public string Surname { get; private set; }
public string Address {
get {
string toret = "N/A";
if ( this.User.IsAdmin() ) {
toret = this.address;
}
return toret;
}
}
private string address;
}
Neither of both solutions is perfect, and both have their own issues, but the problem, at least how you stated it, cannot be solved.
Hope this helps.
Is there a way to define my class so that callers of that class would get a compile time error unless they specified every property of the class, with the additional constraint that the parameters pass be named?
Let's say I have this interface:
public interface IPerson
{
string FirstName {get;}
string MiddleName { get; }
string LastName { get;}
}
And these classes:
public class PersonNeedAllProperties : IPerson
{
public string FirstName { get; private set;} // ideally readonly
public string MiddleName { get; private set;}
public string LastName { get; private set;}
public PersonNeedAllProperties(
string firstName,
string lastName,
string middleName)
{
this.FirstName = firstName;
this.MiddleName = middleName;
this.LastName = lastName;
}
}
public class PersonCanNamePropertiesButNotSadlyNotRequired : IPerson
{
public string FirstName { get; set;} // ideally readonly
public string MiddleName { get; set;}
public string LastName { get; set;}
}
Then the problems with these imho are the following:
var p1 = new PersonNeedAllProperties("lastName", "firstName", "middle");
// woops wrong order because not named.
var p2 = new PersonCanNamePropertiesButNotSadlyNotRequired()
{
FirstName = "firstName",
LastName = "lastName"
}; // woops forgot all about the middlename.
Is there not a way to get a simple POCO object with an initalization similar to person two but that requires that all the properties be named?
Here is the fiddle of the above: https://dotnetfiddle.net/gUk8eT#
To answer your question No, this is not possible.
You ask to be able to force two things:
a) force all properties be set
b) force properties to be named.
These things can be done on their own but they cannot be combined because the methods for doing so are diametrically opposed as described below.
a) To force all properties be set you need to take them as inputs in a constructor.
b) To force properties to be set by name they cannot be specified in the constructor.
Side note: It is possible to provide named parameters to a constructor but it is not possible to force these i.e var person = new Person(firstName: 'John', lastName: 'Doe', middleName: 'A')
The closest you can get is to mark your properties readonly (private set) and have them only be set from within your constructor as you have done in your PersonNeedAllProperties class.
Something that might be a viable alternative is called the Builder Pattern.
This will have an extra class that is responsible for constructing your object, but you still wouldn't be able to get a compile time error, only runtime.
There's a horrible horrible way to almost enforce this. Not by name but by type. i'm not recommending it. but there is a horrible way to do it. did i mention it is horrible?
"any problem in computer science can be solved by adding another layer of indirection" - Wheeler?
Make each of the properties their own distinct type. now you can't pass them in the wrong order or the compiler will tell you that you passed an invalid type.
public class FirstName
{
string Value { get; set; }
}
public class MiddleName
{
string Value { get; set; }
}
public class LastName
{
string Value { get; set; }
}
public interface IPerson
{
FirstName FirstName {get;}
MiddleName MiddleName { get; }
LastName LastName { get;}
}
public class PersonNeedAllProperties : IPerson
{
public FirstName FirstName { get; private set;} // ideally readonly
public MiddleName MiddleName { get; private set;}
public LastName LastName { get; private set;}
public PersonNeedAllProperties(
FirstName firstName,
MiddleName lastName,
LastName middleName)
{
this.FirstName = firstName;
this.MiddleName = middleName;
this.LastName = lastName;
}
}
This can be achieved with a nested class I guess:
public interface IPerson
{
string FirstName { get; }
string MiddleName { get; }
string LastName { get; }
}
public class Person : IPerson
{
public string FirstName { get; private set; }
public string MiddleName { get; private set; }
public string LastName { get; private set; }
//Make sure the parameterless constructor is private
private Person() { }
private Person(string first, string middle, string last)
{
this.FirstName = first;
this.MiddleName = middle;
this.LastName = last;
}
public class Builder
{
private Person person = new Person();
public Builder WithFirstName(string first)
{
person.FirstName = first;
return this;
}
public Builder WithMiddleName(string middle)
{
person.MiddleName = middle;
return this;
}
public Builder WithLastName(string last)
{
person.LastName = last;
return this;
}
public IPerson Build()
{
if (person.FirstName != null
&& person.MiddleName != null
&& person.LastName != null)
return person;
throw new Exception("Cannot build person because reasons...");
}
}
}
Then use it as follows:
var person = new Person.Builder()
.WithFirstName("Rob")
.WithMiddleName("<I have no middle name>")
.WithLastName("Janssen")
.Build();
You can use the With... methods in any order you like:
var person = new Person.Builder()
.WithLastName("Janssen")
.WithFirstName("Rob")
.WithMiddleName("<I have no middle name>")
.Build();
Fiddle here
Edit: Crap; I din't notice the other requirement of compile time errors.
This does, however, 'force' you to set all 3 required fields and 'forces' you to "name" the field using the With... methods which makes it hard to confuse the values and also allows you to specify the values in the order you desire. It also prevents you from instantiating a Person yourself and also allows you to have your private setters (e.g. 'read only' properties) and keeps your interface intact. The only thing missing here is compile time errors; you won't get one here. Maybe Code Contracts can help in that department, but that would at least require some 'team coordination' (e.g. everyone needs to install an extension and have static checking enabled); and I'm not 100% sure if it can be done with code contracts either.
No, interfaces aren't designed to behave that way.
An interface assure you that the classes who implements it will have all the elements declared in the interface. But doesn't make any statements on how they are going to be implemented.
You can accomplish what you want with an abstract class with a custom constructor.
public abstract class Person
{
public abstract string FirstName {get; protected set; }
public abstract string MiddleName { get; protected set; }
public abstract string LastName { get; protected set; }
public Person(string firstName, string middleName, string lastName){
FirstName = firstName;
MiddleName = middleName;
LastName = lastName;
}
}
public class PersonNeedAllProperties : Person
{
public override string FirstName{get; protected set;}
public override string MiddleName{get; protected set;}
public override string LastName{get; protected set;}
public PersonNeedAllProperties(
string firstName,
string lastName,
string middleName)
: base(firstName, lastName, middleName)
{
}
}
The custom constructor force you to complete the names in the child classes.
You can combine this answer with the one of John Gardner using classes instead of strings for the names (firstName, middleName, lastName) to simulate the named parameters.
You need to be aware of the limitations of this method, in C# you cannot inherit from more than one class, so you need to keep this restriction in mind if you decide to implement this solution.
Given the following. What is the difference between having and not have the virtual keyword?
public class Test
{
public Test()
{
this.UserTests = new List<UserTest>();
}
public int TestId { get; set; }
public virtual ICollection<UserTest> UserTests { get; set; }
}
Consider the following Person and Employee classes:
public class Person
{
public string Name { get; set; }
public string WhoAmI()
{
return "I'm just a person and my name is " + this.Name;
}
}
public class Employee : Person
{
public string WhoAmI()
{
return "I'm an employed person and my name is " + this.Name;
}
}
As you can see, the WhoAmI method is not marked with virtual or override in any of the classes. Yet, when you run the following code:
Employee p = new Employee { Name = "John Smith" };
p.WhoAmI(); // yields "I'm an employed person and my name is John Smith"
But, this code:
Person p = new Employee { Name = "John Smith" };
p.WhoAmI(); // yields "I'm just a person and my name is John Smith"
The reason for the difference is simple. In the first case you explicitly instructed the compiler to invoke the more specific WhoAmI by referring to the p variable as an Employee, then Employee.WhoAmI will be invoked.
In the latter case we refer to p as its base class Person hence Person.WhoAmI was invoked.
Polymorphism:
What if we wanted that even when referring to p as Person we'll still be able to invoke the more specific implementation?
That's when the virtual and override come in handy:
public class Person
{
public string Name { get; set; }
public virtual string WhoAmI()
{
return "I'm just a person and my name is " + this.Name;
}
}
public class Employee : Person
{
public override string WhoAmI()
{
return "I'm an employed person and my name is " + this.Name;
}
}
And now it yields the 'correct' results:
Person p = new Employee { Name = "John Smith" };
p.WhoAmI(); // yields "I'm an employed person and my name is John Smith"
Also, when using a Polymorphic list:
var data = new List<Person>();
data.Add(new Person { Name = "Regular Person" });
data.Add(new Employee { Name = "Employed Person" });
foreach (var p in data)
{
p.WhoAmI(); // will call the 'correct' method
}
That means that if some other class will derive from your Test base class, if required, it will be able to override the inherited UserTests property logic with other logic, for example:
private ICollection<UserTest> _userTests;
public class ComplexTest : Test
{
public override ICollection<UserTest> UserTests
{
get { return _userTests.Where(...)} //class-specific logic
set { _userTests = value }
}
}
My person class:
class Person
{
public string FirstName { get; private set; }
public string LastName { get; private set; }
public int Age { get; private set; }
public Person(string firstName,string LastName,int age)
{
this.FirstName = firstName;
this.LastName = LastName;
this.Age = age;
}
public override string ToString()
{
return this.FirstName + " " + this.LastName + " " + this.Age;
}
}
Main:
class Program
{
static void Main(string[] args)
{
Person sallyPerson = new Person("Sally", "Solomon",23);
}
}
Lets say I want to change the Firstname and Age of the person, how would I go about doing so? The FirstName and Age properties are set privately.
You could make the properties public -
class Person
{
// changed private set; to set;
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
So I just realized, all of the answers are assuming that the question you're asking is literally the question you're asking, rather than just an example. But perhaps you were just using it as an example, and you actually need to set a private property of an object that you don't control the source of? In which case, I would say, that's generally a bad idea, but if you really need to do it anyway, there is a way. That way is called "reflection" (this being just one of many kind-of-sketchy things you can do with reflection if you really want). This is a question that you might want to look at, if that is actually what you're after.
More likely, though, the correct response is just don't have the properties be private if you control the source for that class, and are going to want to change them.
class Program
{
static void Main(string[] args)
{
Person sallyPerson = new Person("Sally", "Solomon",23);
sallyPerson = new Person("Newname", "Newvalue", 23);
}
}
This would be one way, another way would be to add methods in the Person object:
public void UpdateFirstName(string newName)
{
this.FirstName = newName;
}
and do sallyPerson.UpdateFirstName("newName");
Or make the properties public with public set and get
The class has been set up as Immutable meaning that once an instance of this class has been constructed it's properties cannot be modified. If you want to be able to construct this class and them modify it's properties you need to make the classes set properties to be public, like so:
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
I'm hoping this is a homework question, otherwise #Brandon Cuff's answer is the obvious one.
Alternatively, you could expose methods to set the fields:
class Person
{
public void SetFirstName(string value)
{
this.FirstName = value;
}
}
I have a class:
public class Person
{
public string FirstName { get; private set; }
public string LastName { get; private set; }
public string Email { get; private set; }
public string Telephone { get; private set; }
public Address Address { get; private set; }
public Person(string firstName, string lastName)
{
//do null-checks
FirstName = firstName;
LastName = lastName;
Address = new Address();
}
public void AddOrChangeEmail(string email)
{
//Check if e-mail is a valid e-mail here
Email = email;
}
public void AddOrChangeTelephone(string telephone)
{
//Check if thelephone has correct format and valid symbols
Telephone = telephone;
}
public void AddOrChangeAdress(Address address)
{
Address = address;
}
The properties that are not in the constructor are optional, i.e. the person does not need an e-mail, address or telephone. However, I want to give the user of the class an opportunity to create the object without having to first provide the required information and then afterwards have to find out what methods to use to add the information.
Questions:
Is it right to create 3 additional overloads to give them that option?
Should i allow public setters on the optional properties and do the validation there?
If the person marries and changes last name, do I need additional method to change the last name or should I make this setter public too, and just require them in constructor?
No.
Yes
Make it public.
Assuming you are going to have more code in the AddOrChange methods such as formatting logic or validation then I'd do the following. Otherwise, I'd completely get rid of the AddOrChange methods:
public class Person
{
private string _email = string.empty;
private string _telephone = string.empty;
private Address _address = new Address();
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email {
get { return _email }
set { AddOrChangeEmail(value); }
}
public string Telephone {
get { return _telephone;}
set { AddOrChangeTelephone(value); }
}
public Address Address {
get { return _address; }
set { AddOrChangeAddress(value); }
}
public Person(string firstName, string lastName)
{
//do null-checks
FirstName = firstName;
LastName = lastName;
}
private void AddOrChangeEmail(string email)
{
//Check if e-mail is a valid e-mail here
_email = email;
}
private void AddOrChangeTelephone(string telephone)
{
//Check if thelephone has correct format and valid symbols
_telephone = telephone;
}
private void AddOrChangeAddress(Address address)
{
_address = address;
}
}
To work with this class you could do any of the following:
Person p = new Person("Tom", "Jones");
p.Telephone = "9995551111";
or
Person p = new Person("Tom", "Jones") { Telephone = "9995551111", Email="spamme#ms.com" }
AddOrChange is equivalent to simple property with public setter, thus you don't need those methods.
public class Person
{
public string FirstName { get; private set; }
public string LastName { get; private set; }
public Email Email { get; set; }
public Telephone Telephone { get; set; }
public Address Address { get; set; }
public Person(string firstName, string lastName)
{
//do null-checks
FirstName = firstName;
LastName = lastName;
}
}
If user during person creation want to provide something additional beside required data, she can use class initializers. Also you can add some optional parameters to constructor.
var bob = new Person("Bob", "Uncle") { Address = someAddress };
If its OK for person to relocate, then why not to use public setter for changing address? Of course, you should check if address is valid. Also if relocating is a business process (i.e. you are relocating someone in hotel) then it would be nice to have this operation on domain service (which will verify if destination room is empty and ready).
Allowing to change name is OK. Usually name is not identity for such entities, thus it could change.
Also, I'd introduced value objects for email and telephone. I think it is not person's responsibility to verify if email address valid. Move that to Email class. Same with Phone and Address.
Is lots of add/change methods and constructor overloads a consequence of DDD?
No, lots of updating methods is not consequence of DDD.
Code
Your Person class can be rewritten to have only 2 updating methods:
class Person
public function Rename(FirstName as Name, LastName as Name) as Person
public function ChangeContacts(
Address as Maybe(of Address),
Phone as Maybe(of Phone),
Mail as Maybe(of MailAddress)) as Person
end class
Rename method accepts two required parameters of special Name type. Validation checks for names happen when names are created, not when they are passed into Person class.
ChangeContacts method accepts three optional parameters any of which can be absent. Special Maybe type indicates that they are optional. Special Address, Phone and MailAddress types indicate that these parameters are already valid and there is no need to validate them again in Person class.
Use case
Person marries and changes last name
Person = Person.
Rename(Person.FirstName, LastNameAfterMarriage)
Person buys new phone number
Person = Person.
ChangeContacts(Person.Address, NewPhoneNumber, Person.Mail)
Person lost phone number
Dim NewPhoneNumber = Maybe.Create(Nothing)
Person = Person.
ChangeContacts(Person.Address, NewPhoneNumber, Person.Mail)
The pattern is to call updating method with old values + some new values.