In C#, is there a way to reference the calling class in a constructor? - c#

I am making a constructor for a class in c#, and I would like it to fill its values differently depending on the type of class that called it.
For example, there is a class called Employer and a class called Person.
When an instance of Employer calls new Person(); I would like the constructor in Person to set the new person's Employed variable to true.
Is this possible in c#?
Tried searching for an answer but was unsure how to word the question.

You can't do it automatically, no. (You could grab a stack trace and parse that, but it would be horribly brittle in the face of JIT compiler optimizations etc.) I'd argue that doing so would make the code brittle and hard to maintain, too - the effect would be like "spooky action at a distance".
The simplest option is to add a bool employed parameter in the constructor instead. Then it's really obvious at every call site how you want the constructed object to behave.

There are a few different ways to do this. The first is to overload the constructor.
public Person() {
this.Employed = false;
}
public Person(bool employed) {
this.Employed = employed;
}
The second that comes to mind is to populate the expected values when instantiating the object.
Person myPerson = new Person {Employed = true };

You can have multiple constructors with different inputs for a class:
public Person() {
this.Employed = false;
}
public Person(bool employed) {
this.Employed = employed;
}
public Person(bool employed,bool _isEmploye) {
if(_isEmploye)
this.Employed = true;
else
this.Employed = false;
}
and use appropriate inputs wherever you call:
Person p = new Person(true,true);

Related

Strange struct constructor compiler workaround

Structs cannot contain explicit parameterless constructors. Such as:
public struct Person
{
public string Name { get; }
public int Age { get; }
public Person() { Name = string.Empty; Age = 0; }
}
However, this is allowed:
public struct Person
{
public string Name { get; }
public int Age { get; }
public Person(string name = null, int age = 0) { Name = name; Age = age; }
}
Any ideas why? Any reason this is bad to do?
The original answer (see the update below):
The second one is allowed because it is not parameterless. But I wouldn't use optional parameters here because it is very confusing - if you call new Person(), your constructor will not be executed (you can check it if you replace the default values other than null and zero):
public struct Person
{
public string Name { get; }
public int Age { get; }
public Person(string name = "Bob", int age = 42)
{
Name = name;
Age = age;
}
}
So new Person() is the same as default(Person), both will use the initobj MSIL instruction instead of calling a constructor.
So why would it be a problem if you could define a default constructor for structs? Consider the following examples.
private void Test()
{
Person p1 = new Person(); // ok, this is clear, use ctor if possible, otherwise initobj
Person p2 = default(Person); // use initobj
Person p3 = CreateGeneric<Person>(); // and here?
Person[] persons = new Person[100]; // do we have initialized persons?
}
public T CreateGeneric<T>() where T : new()
{
return new T();
}
So real parameterless constructors are not allowed for structs in C# (in CLR it is supported, though). Actually parameterless constructors were planned to be introduced in C# 6.0; however, it caused so many compatibility problems that at the end this feature was removed from the final release.
Update 2022:
Starting with C# 10 parameterless struct constructors are actually supported due to struct records with field initializers. From the docs:
If a record struct does not contain a primary constructor nor any instance constructors, and the record struct has field initializers, the compiler will synthesize a public parameterless instance constructor.
But not as if everything was obvious now. Let's revisit the examples above:
new Person(): Even this case is a bit confusing. Obviously, if you have a parameterless constructor, it will call that one. But unlike in case of classes, if there is no parameterless constructor, it will use the initobj instruction even if there is a constructor overload with optional parameters only (the OP's 2nd example).
default(Person): This is clear, the initobj instruction will be used
CreateGeneric<Person>(): It turns out that it also invokes the parameterless struct constructor... well, at least for the first time. But when targeting .NET Framework, it fails to invoke the constructor for subsequent calls.
new Persons[100]: No constructor call (which is actually expected)
And the feature has some further unexpected implications:
If a field has an initializer and there are only parameterized constructors, then new MyStruct() does not initialize the fields.
Parameter default value initialization like void Method(Person p = new Person()) also fails to call the parameterless constructor. In the meantime this was 'fixed' by emitting CS1736 if there is a parameterless constructor; otherwise, it is allowed and means just default.
If you target .NET Framework, Activator.CreateInstance(Type) also works incorrectly (behaves the same way as CreateGeneric<Person>() above): the constructor is invoked only for the first time.
Expression.New(Type) also works incorrectly, not just in .NET Framework but on all .NET/Core platforms prior version 6.0
And the story is not over. Now it seems that auto-synthesizing parameterless constructor will be removed, which makes the first bullet point above illegal and will be a breaking change from C# 10. But there are also further open issues such as this one, which also needs some changes to language specification.
A parameter-less constructor for a struct will make it more tempting to create mutable structs which are considered evil.
var person = new Person();
person.Age = 35;
...
I am sure there are other reasons, but a major pain is that because they are copied as they are passed around and it is easy to change the wrong struct and therefore easier to make an error that is difficult to diagnose.
public void IncreaseAge(Person p)
{
p += 1; // does not change the original value passed in, only the copy
}
Any ideas why?
This constructor is not implicitly parameterless -- it has 2 parameters.
Any reason this is bad to do?
Here is a reason: The code can be hard to reason about.
You may expect that if you wrote:
var people = new Person[100];
that all People in that array would have the default values for the optional arguments but this is untrue.
The values of optional arguments are hardcoded into the calling code.
If later you choose the change your defaults, all compiled code will retain the values it was compiled with.

"Writable" reference to object

Not sure I'm able to formulate this question in a way someone would simply understand, so lets have a cool marketing example:
public class Part
{
public MemberType member;
...
}
public class Product
{
public Part part1;
...
}
...
Product product = new Product();
I need to modify the public product's part1. So, the natural method is to write something like:
product.part1 = new Part();
Now, an algorithm (let's say a sort of search one) would go through the product object and identify the part1 as an interesting part and returns reference to it:
Part Search(Product product)
{
Part part = null;
...
part = product.part1;
...
return part;
}
...
interesting_part = Search(product);
We can alter the product object via the interesting_part like
interesting_part.member = whatever;
Now, the question: in c/c++ if the Product.part1 is pointer to Part and Search returns address of this pointer, we could replace the part1 just by assigning new value to this address. AFAIK this is not possible for c# reference:
interesting_part = new Part();
Just creates new object and copies its reference to the interresting_part, but without knowing the member parent (product object), we are not able to modify the (product.part1) reference, just its content. We would need second level of the reference.
Is there something like "ref reference" type which would accept reference addresses? In such hypothetical case the search would return ref Part and assigning to such value would replace the referenced object with the new one.
Thanks.
You could create a Reference class
class Reference<T>
{
private Func<T> m_Getter;
private Action<T> m_Setter;
public Reference(Func<T> getter, Action<T> setter)
{
m_Getter = getter;
m_Setter = setter;
}
public T Value
{
get{return m_Getter();}
set{m_Setter(value);}
}
}
Now you can say
Reference<Part> Search(Product product)
{
Part part = null;
...
part = product.part1;
var reference=new Reference<Part>(()=>product.part, (value)=>product.part1=value);
return refernce;
}
var partReference = Search(product);
partReference.Value = someNewPart;
In a very similar situation, I keep a reference of the parent in each child object. Simple and works.
public class Part
{
public MemberType member;
...
public Product parent;
Part(Product p)
{
parent = p;
}
}
public class Product
{
public Part part1;
...
}
I don't think you can do that. You would need to mutate a reference to you product object, or have some other added layer of reference.
So you need to build a Proxy object. The Product would get a reference to the Proxy and the (hidden) Part can be exchanged. This is a common OO design pattern. Of course the Proxy can delegate method calls to the Part.
If you want to change the field, you can do this,
class Program
{
static void Main(string[] args)
{
var holder = new Holder();
holder.CurrentPart = new Part() { Name = "Inital Part" };
Console.WriteLine(holder.CurrentPart.Name);
TestRef(ref holder.CurrentPart);
Console.WriteLine(holder.CurrentPart.Name);
Console.ReadKey();
}
public static void TestRef(ref Part part)
{
part = new Part() { Name = "changed" };
}
}
public class Part
{
public string Name;
}
public class Holder
{
public Part CurrentPart;
}
This won't work with property, indexers and so.
As far as I know, there isn't any way to alter an object's "parent" without having a reference to it. So I believe the official answer to your question as written is "no".
That said, there are many ways to accomplish the task as written. The easiest option is to add a reference to the parent from the part object. You end up with something like:
public class Part
{
public Product parentProduct;
public MemberType member;
...
}
Now whenever you have a part object you also know what product the part goes with (IF it does indeed go with a part at all). This is not necessarily a bad coding style but there certainly are pitfalls. You can update the product, but forget to update the parts in that product, you are coding so that parts have one product, but what if that part has many products? You can see how this works, but it can get complicated.
Taking this and making it more generic you can have reference the parent as an object type. That looks like:
public class Part
{
public object parent;
public MemberType member;
...
}
Now when you want to use the parent you can write something like:
var parentProduct = myPart.parent as Product;
This will convert the parent to a product or will assign null if the parent is not of the type Product. Now parts can have parents of any given type you would want and you have made the pattern more flexible.
One final pattern I know people use frequently is delegates. This allows you to pass in a function effectively modifying the way "search" is working. Say what you really want to do is search, then process the results in some manner, but you want that processing to be flexible (this may be what you were doing with the results). In that case, you can use delegates as follows:
// define the delegate
public delegate void ProcessResultDelegate(Product result, Part interestingPart);
// an example search function
public static void RunSearch(IEnumerable<Product> products, ProcessResultDelegate processingHelper)
{
// run the search... then call the processing function
processingHelper(searchResult, interestingPart);
}
This pattern is more useful when you want to modify the behavior of a routine rather than the return value from that routine.
Anyways, hope these patterns help some!

how to extend base class functionality

I have a class:
public class Person {
public string FirstName = "";
public string LastName = "";
}
and a derived class:
public class HRPerson : Person {
public string GetSomething() {
//calculate something
}
}
Essentilly, I'm wanting to extend the functionality of the base class. The use looks like this, where GetAllPerson returns List<Person>.
class Program
{
static List<HRPerson> GetAllHRPerson()
{
List<HRPerson> HRPersonList = new List<HRPerson>();
foreach (Person person in GetAllPerson)
{
HRPersonList.Add(person);
}
return HRPersonList;
}
}
It doesn't compile, saying that there is no overload for the parameter, and when I try to cast person to HRPerson, I get the runtime error "unable to cast object of type Person to type HRPerson" error.
How do I go about adding additional functionality like this?
It sounds like your GetAllPerson is returning some non-HR people...
Assuming that's the case and you just want to filter those out, it's easiest to use LINQ's OfType method:
static List<HRPerson> GetAllHRPerson()
{
return GetAllPerson().OfType<HRPerson>().ToList();
}
(Side note: please avoid public fields like this, other than for constants. Fields should be an implementation detail, not part of your public API.)
Of course if none of your Person instances are actually instances of HRPerson, that's not going to help you. You can't change the type of an instance once it's been created. It's not really clear what your situation is - if this answer doesn't help you, please provide more details.
EDIT: I'm still not really sure that you want an extension method, but if you do, it would be something like:
public static class PersonExtensions
{
public static string GetSomething(this Person person)
{
// Do something with the given Person
}
}
You can then call that on any Person as if it were an instance method:
Person person = ...;
string something = person.GetSomething();
But this is not polymorphic - it's not that you're changing anything about the Person object, which your description still makes it sound like you really want to do...
Based on your comments to Jon Skeet's answer, is this what you are looking for:
Create a subclass of Person, for example, NamedPerson. Give NamedPerson a method GetFullName, which returns the full name of the Person.
Then create a subclass HRPerson from NamedPerson, and override GetFullName to return the name in a slightly different format. CCPerson would also be subclassed from NamedPerson.
You have no control over Person, but you have full control over NamedPerson. Then what you want is a list of NamedPersons, not of HRPersons. This list could contain bare NamedPersons, or HRPersons, or CCPersons, but all objects on the list would be NamedPersons or subclasses of it, so they would all have GetFullName.

Is it bad practice to modify the variable within a method?

Which method style is better?
Is it generally bad practice to modify the variable within a method?
public class Person
{
public string Name { get; set;}
}
//Style 1
public void App()
{
Person p = new Person();
p.Name = GetName();
}
public string GetName()
{
return "daniel";
}
//Style 2
public void App()
{
Person p = new Person();
LoadName(p)
}
public void LoadName(Person p)
{
p.Name = "daniel";
}
There are times when both styles may make sense. For example, if you're simply setting the name, then perhaps you go with the first style. Don't pass an object into a method to mutate one thing, simply retrieve the one thing. This method is now more reusable as a side benefit. Think of it like the Law of Demeter or the principle of least knowledge.
In other cases, maybe you need to do a wholesale update based on user input. If you're displaying a person's attributes and allowing the user to make modifications, maybe you pass the object into a single method so that all updates can be applied in one spot.
Either approach can be warranted at different times.
I think the code is more clear and readable when methods don't change objects passed. Especially internal fields of passed object.
This might be needed sometimes. But in general I would avoid it.
Updated based on comment (good point)
I agree with Anthony's answer. There are times when both styles may make sense.
Also, for more readability you can add the LoadName function in person class.
public void App()
{
Person p = new Person();
p.LoadName(); //If you need additional data to set the Name. You can pass that as Parameter
}
You are accessing the data using properties which technically is by a methods. What you are worried is property accessing iVar or internal variable. There reason why it is generally bad to allow access of iVar is because anyone can modify the variables without your knowledge or without your permission, if its through a methods (properties), you have the ability to intercept the message when it get or set, or prevent it from getting read or write, thus it is generally said to be the best practice.
I agree with Ron. Although your particular example could be slightly contrived for posting reasons, I would have a public getter for Name, and a private setter. Pass the name to the constructor, and the Name property will get set there, but afterwards can no longer be modified.
For example:
public class Person
{
public string Name { get; private set; }
public Person( string name)
{
Name = name;
}
}

Constructors with the same argument type

I have a Person object with two constructors - one takes an int (personId), the other a string (logonName). I would like another constructor that takes a string (badgeNumber). I know this can't be done, but seems it might be a common situation. Is there a graceful way of handling this? I suppose this would apply to any overloaded method. Code:
public class Person
{
public Person() {}
public Person(int personId)
{
this.Load(personId);
}
public Person(string logonName)
{
this.Load(logonName);
}
public Person(string badgeNumber)
{
//load logic here...
}
...etc.
You could perhaps use factory methods instead?
public static Person fromId(int id) {
Person p = new Person();
p.Load(id);
return p;
}
public static Person fromLogonName(string logonName) {
Person p = new Person();
p.Load(logonName);
return p;
}
public static Person fromBadgeNumber(string badgeNumber) {
Person p = new Person();
// load logic
return p;
}
private Person() {}
You might consider using custom types.
For example, create LogonName and BadgeNumber classes.
Then your function declarations look like...
public Person(LogonName ln)
{
this.Load(ln.ToString());
}
public Person(BadgeNumber bn)
{
//load logic here...
}
Such a solution might give you a good place to keep the business logic that governs the format and usage of these strings.
You have four options that I can think of, three of which have already been named by others:
Go the factory route, as suggested by several others here. One disadvantage to this is that you can't have consistent naming via overloading (or else you'd have the same problem), so it's superficially less clean. Another, larger, disadvantage is that it precludes the possibility of allocating directly on the stack. Everything will be allocated on the heap if you take this approach.
Custom object wrappers. This is a good approach, and the one I would recommend if you are starting from scratch. If you have a lot of code using, e.g., badges as strings, then rewriting code may make this a non-viable option.
Add an enumeration to the method, specifying how to treat the string. This works, but requires that you rewrite all the existing calls to include the new enumeration (though you can provide a default if desired to avoid some of this).
Add a dummy parameter that is unused to distinguish between the two overloads. e.g. Tack a bool onto the method. This approach is taken by the standard library in a few places, e.g. std::nothrow is a dummy parameter for operator new. The disadvantages of this approach are that it's ugly and that it doesn't scale.
If you already have a large base of existing code, I'd recommend either adding the enumeration (possibly with a default value) or adding the dummy parameter. Neither is beautiful, but both are fairly simple to retrofit.
If you are starting from scratch, or only have a small amount of code, I'd recommend the custom object wrappers.
The factory methods would be an option if you have code which heavily uses the raw badge/logonName strings, but doesn't heavily use the Person class.
No.
You might consider a flag field (enum for readability) and then have the constructor use htat to determine what you meant.
That won't work. You might consider making a class called BadgeNumber that wraps a string in order to avoid this ambiguity.
You cannot have two different constructors/methods with the same signature, otherwise, how can the compiler determine which method to run.
As Zack said, I would consider creating an "options" class where you could actually pass the parameters contained in a custom type. This means you can pretty much pass as many parameters as you like, and do what you like with the options, just be careful you dont create a monolithic method that tries to do everything..
Either that, or vote for the factory pattern..
You could use a static factory method:
public static Person fromLogon(String logon) { return new Person(logon, null); }
public static Person fromBadge(String badge) { return new Person(null, badge); }
As has been suggested, custom types is the way to go in this case.
If you are using C# 3.0, you can use Object Initializers:
public Person()
{
}
public string Logon { get; set; }
public string Badge { get; set; }
You would call the constructor like this:
var p1 = new Person { Logon = "Steve" };
var p2 = new Person { Badge = "123" };
Only thing I can think of to handle what you're wanting to do is to have to params, one that describes the param type (an enum with LogonName, BadgeNumer, etc) and the second is the param value.
You could switch to a factory style pattern.
public class Person {
private Person() {}
public static PersonFromID(int personId)
{
Person p = new Person().
person.Load(personID);
return p;
this.Load(personId);
}
public static PersonFromID(string name)
{
Person p = new Person().
person.LoadFromName(name);
return p;
}
...
}
Or, as suggested, use custom types. You can also hack something using generics, but I wouldn't recommend it for readability.
Depending on your business constraints:
public class Person
{
public string Logon { get; set; } = "";
public string Badge { get; set; } = "";
public Person(string logon="", string badge="") {}
}
// Use as follow
Person p1 = new Person(logon:"MylogonName");
Person p2 = new Person(badge:"MyBadge");
How about ...
public Person(int personId)
{
this.Load(personId);
}
public Person(string logonName)
{
this.Load(logonName);
}
public Person(Object badgeNumber)
{
//load logic here...
}

Categories

Resources