Not really 2 constructors, rather 3 but 2 of them are overloaded.
This one was originaly on some tutorial that I watched a while back.
public Animal()
{
this.height=0;
this.weight=0;
this.name="No Name";
this.sound = "No Sound";
}
public Animal(double height, double weight, string name, string sound)
{
this.height=height;
this.weight=weight;
this.name=name;
this.sound = sound;
}
I remember this from software dev classes, so I was wondering if it made any sense to write it this way, and if not what could go wrong if this were on my code?
public Animal(double height=0, double weight=0, string name="No Name", string sound="No Sound")
{
this.height=height;
this.weight=weight;
this.name=name;
this.sound = sound;
}
Because I really don't know if I can put default values in class constructor like this.
Sure you can. And for most code you won't see a big difference (other than in the first case you'll have to supply either all of the parameters, or none).
But there is a subtle difference nevertheless, and it can bite you later on.
See, the first snippet declares a so-called default constructor and a custom one, but the second snippet only declares a custom constructor.
Here's a generic function:
public static T Create<T>()
where T : new()
{
return new T();
}
Here's what you'll get if you call Create<Animal>():
error CS0310: 'Animal' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Program.Create<T>()'
So your custom constructor does not replace a default constructor in cases where it's expected.
Same goes for reflection:
Activator.CreateInstance<Animal>();
Will result in a runtime exception:
Unhandled Exception: System.MissingMethodException: No parameterless constructor defined for this object.
So providing an accessible default constructor has also a semantic meaning. It tells an instance of your class is still meaningful when created through its default constructor, and doesn't require additional parameters. It can be used in scenarios involving serialization for instance (some serializers require a default constructor, other don't).
I would say it's mainly about communication. In the first case you either provide all the values, or nothing(..and you get the defaults). The person who wrote that code may have had a good reason for only those two options.
In the second case you are more flexible, for instance you could choose to provide only one parameter.. it could be the case that such an object would become invalid. As with most things.. it all depends
Related
I once again am struggling with reflection. I just give you the piece of code that my debugger does not bite:
public bool HandleCommand(string command)
{
MethodInfo m = methods.FirstOrDefault(t => t.GetCustomAttribute<CommandAttribute>().Name == command);
ICommandSet set =(m.DeclaringType)Activator.CreateInstance(m.DeclaringType);
m?.Invoke(set, null);
return true;
}
Basically, this code is inside a class called CommandHandler. When it's constructed, it loops over all the types in the executing assembly that implement a certain interface, and store all their methods that have a CustomAttribute attached to it in List; For this question's purpose I just assume that everything is working there. The attribute has just one property:
[AttributeUsage(AttributeTargets.Method)]
public class CommandAttribute : Attribute
{
public string Name { get; set; }
public CommandAttribute(string name)
{
Name = name;
}
}
Now in the method you saw above, the HandleCommand() method, I store the method which's name property is equal to the string I passed in in a MethodInfo m. Now my question essentially is, how I properly Invoke this method. m.Invoke needs an object that calls it, and because passing in "this" does not work, and examples online always passed in an instance of the class it was defined in, I figured I needed to create an instance of the class m was defined in and just pass this into the Invoke() method. In practice, this is a lot harder than I thought, and my best guess is what you can see above, with the activator.
ICommandSet set =(m.DeclaringType)Activator.CreateInstance(m.DeclaringType);
First of all, I know for sure that the class that m is declared in implements ICommandSet, because this is a creterium for a type to be inspected for the methods. So this is why I say "ICommandSet set". Then the Activator shall create this instance. But it does not work. The only error message provided states that m is a variable but is used like a type. However, when I pass it in as a param to Activator.CreateInstance() the compiler seems to dig it just fine. I absolutely don't know how I might fix this problem, as I don't really understand what is the problem. Is there anyone out there who can help me?
Also, all the methods are defined in different classes and even projects, so I don't know which class the methods are defined in.
The reason you're receiving this is your syntax is wrong. You cannot perform a cast with a variable dereference as the desire type. As you already know you wish to treat "set" as an "ICommandSet" cast to that instead.
var set = (ICommandSet) Activator.CreateInstance(m.DeclaringType);
You can also do it safe
var set = Activator.CreateInstance(m.DeclaringType) as ICommandSet;
I'm writing an exception that inherits from ArgumentOutOfRangeException and I want to write constructors that derive from the two base overloads base(string paramName) and base(string paramName, string message) but I want to provide default values for paramName in both constructors and a default value for message in the second. What is the best way to do this? (If it helps, the default value for paramName will be the same in both).
I've thought of overriding the constructor with a single constructor with a third boolean parameter to determine which constructor to call and calling that constructor, but after some testing found out that fails on so many levels.
Here is an example of what I'm trying to do:
public class TrainingSetCardinalityMismatch : ArgumentOutOfRangeException
{
public TrainingSetCardinalityMismatch(string paramName = "trainingSets") : base(paramName)
{
//code here
}
public TrainingSetCardinalityMismatch(string paramName = "trainingSets", message = "Number of training sets provided must match number of answers provided") : base(paramName, message)
{
//code here
}
}
You could call the other constructor with your default values like so
public CustomException(string paramName = "defaultName") : this(paramName, null)
{
}
public CustomException(string paramName = "defaultName", string message = "defaultMessage") : base(paramName, message)
{
}
Well from the question, I can see 2 possibilities.
You always want the message (second argument)
You sometime want the message, sometime not and sometime a different message.
In the first case, you would simply remove the definition of the first constructor. You will always have the message if you don't specify the second argument.
public class TrainingSetCardinalityMismatch : ArgumentOutOfRangeException
{
public TrainingSetCardinalityMismatch(
string paramName = "trainingSets",
message = "Number of training sets provided must match number of answers provided")
: base(paramName, message)
{
//code here
}
}
Then you could call it that ways:
// default param name + default message
throw new TrainingSetCardinalityMismatch();
// custom param, default message
throw new TrainingSetCardinalityMismatch("custom param");
// custom param, custom message
throw new TrainingSetCardinalityMismatch("custom param", "custom message");
However, it won't allows default param but with custom message.
If you want that, you have a few possibilities:
One would be to have a constant for the default message and specify it explicitly instead of the hard coded string.
Another might be to change parameter order if message need to be customized most of the time.
Another one would be to have a static functions that raise the exception.
Another one could be to set the default to null if when null is specified remplace by default value. That way, you can use an empty string if you really want no message.
Another one is to have 2 exception classes (say TrainingSetCardinalityMismatchAandTrainingSetCardinalityMismatchB`) and each one has a single constructor.
Another want would be to use an enum instead of a string when using predefined messages and then constructor with custom message would not have any default as it would be used only for specific message.
Usually, I prefer the last way and then I could use resource and a bit of code to load the appropriate string from the enum identifier which is relatively easy in C# as you can to enum_var.ToString() to get a name and use that name to load a resource by its name using the resource manager (see https://learn.microsoft.com/en-us/dotnet/api/system.resources.resourcemanager?view=netframework-4.7.2).
Why not create your own constructors and call the base ones like i've shown below
class MyArgumentOutOfRangeException : ArgumentOutOfRangeException
{
public MyArgumentOutOfRangeException(string myName):base("PlaceDefaultNamepropValue")
{
// do something with passed my name
}
public MyArgumentOutOfRangeException(string myname, string mymessage):base("PlaceDefaultNamepropValue", "PlaceDefaultMessagepropValue")
{
// do something with passed my name
// do something with passed my message
}
}
class MyOtherArgumentOutOfRangeException : ArgumentOutOfRangeException
{
public MyOtherArgumentOutOfRangeException(string myName) : this("PlaceDefaultNamepropValue",string.Empty)
{
// do something with passed my name
}
public MyOtherArgumentOutOfRangeException(string myname, string mymessage) : base("PlaceDefaultNamepropValue", "PlaceDefaultMessagepropValue")
{
// do something with passed my name
// do something with passed my message
}
}
Other than needing to define the type of message (use string message = "..."), your posted code seems to be functional and doing what you want. So I assume the core of your question is:
What is the best way to do this? .... I've thought of overriding the constructor with a single constructor with a third boolean parameter to determine which constructor to call and calling that constructor.
As a general rule, I advocate against "choose your own adventure" booleans. While they work on a technical level, there are better alternatives here.
Parameters with default values are, by definition, optional parameters. This means you're already able to decide your consumer's constructor selection based on whether the consumer passed the a non-default message value. If they didn't, then they're clearly choosing to use the first option. If they did, then they're clearly choosing the second option. They don't need to then also specify a boolean.
Does it really matter whether you don't initialize message, or instead explicitly pass null or String.empty when the consumer doesn't provide a message value? Because if not, then there's no reason to even try and distinguish between the two base constructors.
Method overloading inherently exists to give users a way to differentiate between different sets of input parameters, and each overloaded body has its own method (which you can choose to chain or not) so you have total control over what happens in which case. Your boolean would be a (IMO poor) substitute for a cleaner method overload.
CYOA booleans tend to only seem viable when you are the consumer of your own code because "I know how I designed this to work". That's often something which leads to avoiding good practice and clean coding. While it will work on a technical level, it's not a good/clean solution and it eventually teaches you bad habits. In most cases, when I use someone else's library, I expect to use the method names to decide what I want to do, not a set of boolean parameters. There are of course exception to this, but they are few and far between. When I've picked the method to use, the parameters should be easy to understand and supply, rather than forcing the user to decide separate behaviors.
Encapsulation suggests that your implementation needs to hide complexities from the consumer of your class, where possible. Which means that you're allowed to use a branching structure inside your class, but you shouldn't require the consumer to knowingly make this choice - your class exists to do this for the consumer and simplify the consumer's workload. If you pass the buck to your consumer, then what is your class' value? What does it do for you/the end user? (Note: Don't misinterpret this as an anti-IOC argument. IOC is a good thing, it just isn't really done via booleans. Using IOC, you'd be injecting behavior objects instead of boolean values).
According to MSDN's design guide for constructors,
"If you don’t explicitly declare any constructors on a type, many languages (such as C#) will automatically add a public default constructor. (Abstract classes get a protected constructor.)
Adding a parameterized constructor to a class prevents the compiler from adding the default constructor. This often causes accidental breaking changes."
Why not:
"If you don’t explicitly declare any default constructors on a type, many languages (such as C#) will automatically add a public default constructor. (Abstract classes get a protected constructor.)"
What is the reason behind this?
Because not all classes should be constructed parameterless.
Consider a class that is designed to implement the interface between your application and a file on disk. It would be very inconvenient having to handle the case where the object is constructed without specifying which file to manage.
As such, since the main point of creating a non-static class is that you want to create objects of it, you're spared having to add an empty parameterless constructor if that is all you want to have.
Once you start adding constructors at all, then the automagic is disabled and no default constructor will be provided.
If I define a custom constructor which means my object need initialising in a specific way e.g.:
class Customer
{
public Customer(string name) { this.Name = name; }
public string Name { get; }
}
If the compiler also added public Customer() then you could bypass the requirement to initialise a customer with a name.
If no constructor is present, there is no way to new up an instance of the class.
So, when you provide a constructor, there is at least one way to construct the class. If no constructor at all is provided, one is provided by default, so that you can actually build the class.
This answer's the question of why the default constructor exists, but not why it doesn't exist when you don't create your own parameterless constructor.
If a default constructor were to be provided when you've already provided one, this could lead to unintended consuming of the class. An example of this has been pointed out in another answer, but just as another:
public class Foo
{
private readonly IDbConnection _dbConnection;
public Foo(IDbConnection dbConnection)
{
if (dbConnection == null)
throw new ArgumentNullException(nameof(dbConnection));
_dbConnection = dbConnection;
}
public Whatever Get()
{
var thingyRaw = _dbConnection.GetStuff();
var thingy = null; // pretend some transformation occurred on thingyRaw to get thingy
return thingy;
}
}
If a default constructor were to be automatically created in the above class, it would be possible to construct the class without its dependency IDbConnection, this is not intended behavior and as such, no default constructor is applied.
It annoys me that I am required to have them, for an example consider the case
public class IsEquipmentAvailable : Specification<Equipment>
{
public IsEquipmentAvailable() : base(equipment => equipment.CartEquipments
.All(o => o.RentState == RentState.Done))
}
However, I am not allowed to write this as I need to add {}, in c# that is at least 2 extra lines of the boilerplate code that do nothing. If I want to support directed expression graph chain calls or just instantiating element from an expression, it becomes even worse.
public class IsEquipmentAvailable : Specification<Equipment>
{
public IsEquipmentAvailable(Expression<Func<Equipment, bool>> expression)
: base(expression)
{
}
public IsEquipmentAvailable(ISpecification<Equipment> specification)
: base(specification)
{
}
public IsEquipmentAvailable() : base(equipment => equipment.CartEquipments
.All(o => o.RentState == RentState.Done))
{
}
}
The functional programming side of me laughs from ignorance because he does not know better. Sometimes there are valid reasons why things are the way they are, so I would like to know reasoning behind this.
The language does allow for an omission - just the opposite one to the one you we're looking for (10.11.1):
All instance constructors (except those for class object) implicitly include an invocation of another instance constructor immediately before the constructor-body
and:
If an instance constructor has no constructor initializer, a constructor initializer of the form base() is implicitly provided. Thus, an instance constructor declaration of the form
C(...) {...}
is exactly equivalent to
C(...): base() {...}
So, there's no exception for constructors that have initializers because, per the language spec, all constructors do in fact have initializers.
Also, the language is quite consistent here, when you think about it - the only places where you're allowed to completely omit the body of a method are where you are, specifically, prohibited from supplying a body - such as extern constructors, as mentioned in the comments, or abstract methods. Everywhere else, you must supply a body, even if you choose to make it empty.
Is there an app or website where I can input parameter info (types and variable names), their defaults, and have it generate all the combinations of method overloads?
I have a class where the constructor can take in five parameters of different types. The parameters get mapped to properties, none of which have public setters. Each parameter has a default value.
I want my class to have overloaded constructors for all the various combinations of the parameters (ranging from no parameters to any and all combinations of the five parameters). To make it more confusing, one of the parameters can be passed in as a specific type or as a string, and I want the various combinations of overloads to take that into consideration.
Update:
I agree this design may not be the best. The class in question is one I'm using in a similar fashion to the PropertyMetadata class of WPF's DependencyProperty. A value is assigned for the property backing, and a new instance of the metadata class is passed in at that time. It's forcing my hand to create this cascading series of constructor overloads. Example:
private ModelProperty<UserModel, string> firstNameProperty =
RegisterProperty(p => p.FirstName, new ModelPropertyMetadata(**** lots of overloads here ****));
public string FirstName
{
get { return GetValue(firstNameProperty); }
set { SetValue(firstNameProperty, value); }
}
Maybe that's not the best design. I could possibly extend ModelPropertyMetadata to new classes which describe specific overloads, but that just seems like its pushing the problem somewhere else. Any thoughts on how to make this design better?
Take a look at optional parameters - these should help you avoid multiple overloads and still provide multiple ways to call a constructor. This is a .NET 4.0 feature.
Why not using optional parameters?
public MyClass(String myVar = null, Int32 v0 = 5, ...) { .. }
You can call the ctor this way:
new MyClass(v0: 10);
I don't know of one, but might I suggest you create a simple type that holds the parameters and has the defaulting logic and you pass that type into your class as what your suggesting will be difficult to maintain.