C# constructor with optional parameters - c#

I have a simple question about constructors in C#. Will these two code snippets behave the same way?
Code snippet #1:
public class foo
{
public foo(string a = null, string b = null)
{
// do testing on parameters
}
}
Code snippet #2:
public class foo
{
public foo()
{
}
public foo(string a)
{
}
public foo(string a, string b)
{
}
}
EDIT:
And if I add this to the code snippet #1? It may look a really bad idea, but I'm working on refactoring a legacy code, so I'm afraid if I do sth that will cause damage to other piece of that uses that class.
public class foo
{
public foo(string a = null, string b = null)
{
if (a == null && b == null)
{
// do sth
}else if (a != null && b == null)
{
// do sth
}
if (a != null && b != null)
{
// do sth
}
else
{
}
}
}

The answer is no, the two are not going to behave the same.
The first snippet does not let your constructor decide if it has been called with a default parameter for a and/or b, or the caller has intentionally passed null. In other words, passing nulls intentionally becomes allowed, because you cannot implement a meaningful null check.
Another aspect in which these two code snippets would definitely differ - using constructors through a reflection:
The first snippet would provide one constructor. Reflection callers would need to deal with passing two parameters to it, or allowing optional parameters with binding flags (look at the demo provided by Jcl).
The second snippet would provide three separate constructors. Reflection callers would need to pick the one they wish to use.

No. Try using named arguments. The overload version will not compile. Because a hasn't been given a value in the latter case.
var test = new foo1(b: "nope");
var test2 = new foo2(b: "nope");//CS7036 : There is no argument given that corresponds to the required formal parameter of

if your are looking for a way to create an object with optional parameters just create inside your class a static factory method with optional or named parameter:
public class Foo
{
public Foo(string a, string b, string c) { }
public static Foo createInstance(string a = null, string b = null, string c = null) => new Foo(a, b, c);
}

Related

Comparison to null evaluates to true for both expr == null and expr != null

I am seeing something very strange, which I cannot explain. I am guessing some edge case of C# which I am not familiar with, or a bug in the runtime / emitter?
I have the following method:
public static bool HistoryMessageExists(DBContext context, string id)
{
return null != context.GetObject<HistoryMessage>(id);
}
While testing my app, I see it is misbehaving - it is returning true for objects I know do not exist in my db. So I stopped at the method and in Immediate, I ran the following:
context.GetObject<HistoryMessage>(id)
null
null == context.GetObject<HistoryMessage>(id)
true
null != context.GetObject<HistoryMessage>(id)
true
GetObject is defined like so:
public T GetObject<T>(object pk) where T : DBObject, new()
{
T rv = Connection.Get<T>(pk);
if (rv != null)
{
rv.AttachToContext(this);
rv.IsInserted = true;
}
return rv;
}
Interestingly, when casting the expression to object, the comparison is evaluated correctly:
null == (object)context.GetObject<HistoryMessage>(id)
true
null != (object)context.GetObject<HistoryMessage>(id)
false
There is no equality operator overriding.
Edit: It turns out there is an operator overload, which was incorrect. But then why would the equality evaluate correctly in the internal method generic GetObject, where rv is of type HistoryMessage in this case.
public class HistoryMessage : EquatableIdentifiableObject
{
public static bool HistoryMessageExists(DBContext context, string id)
{
var rv = context.GetObject<HistoryMessage>(id);
bool b = rv != null;
return b;
}
public static void AddHistoryMessage(DBContext context, string id)
{
context.InsertObject(new HistoryMessage { Id = id });
}
}
public abstract partial class EquatableIdentifiableObject : DBObject, IObservableObject
{
public event PropertyChangedEventHandler PropertyChanged;
[PrimaryKey]
public string Id { get; set; }
//...
}
public abstract partial class EquatableIdentifiableObject
{
//...
public static bool operator ==(EquatableIdentifiableObject self, EquatableIdentifiableObject other)
{
if (ReferenceEquals(self, null))
{
return ReferenceEquals(other, null);
}
return self.Equals(other);
}
public static bool operator !=(EquatableIdentifiableObject self, EquatableIdentifiableObject other)
{
if (ReferenceEquals(self, null))
{
return !ReferenceEquals(other, null);
}
return !self.Equals(other);
}
}
public abstract class DBObject
{
[Ignore]
protected DBContext Context { get; set; }
[Ignore]
internal bool IsInserted { get; set; }
//...
}
What is going on here?
As you already clarified, the == operator failed for your type because you had an overload that was incorrect.
When casting to object, the == operator worked correctly since it was object's implementation of == that was used and not EquatableIdentifiableObject's.
In the method GetObject the operator evaluates correctly because it is not EquatableIdentifiableObject's implementation of == that is being used. In C# generics are resolved at run-time (at least in the sense that is relevant here) and not at compile time. Note that == is static and not virtual. So the type T is resolved at run-time but the call to == has to be resolved at compile time. At compile time when the compiler resolves == it will not know to use EquatableIdentifiableObject's implementation of ==. Since the type T has this constraint: where T : DBObject, new(), DBObject's implementation (if any) will be used. If DBObject does not define == then the implementaion of the first base class that does so (up to object) will be used.
A few more comments about EquatableIdentifiableObject's implementation of ==:
You could replace this part:
if (ReferenceEquals(self, null))
{
return ReferenceEquals(other, null);
}
with:
// If both are null, or both are the same instance, return true.
if (object.ReferenceEquals(h1, h2))
{
return true;
}
It would be more robust to replace
public static bool operator !=(EquatableIdentifiableObject self, EquatableIdentifiableObject other)
{
...
}
with:
public static bool operator !=(EquatableIdentifiableObject self, EquatableIdentifiableObject other)
{
return !(self == other);
}
The way you define the signature for == is slightly misleading. The first parameter is named self and the second is named other. That would be ok if == was an instance method. Since it is a static method, the name self is a bit misleading. Better names would be o1 and o2 or something along this line so that the two operands are treated on a more equal footing.
There can be several overloads of operator ==(...) as you now know. Some of them can be C# built-in overloads, and others can be user-defined operators.
If you hold the mouse over the != or == symbol in Visual Studio, it will show you what overload is chosen by overload resolution (up till VS2013 it would only show it if the chosen overload was actually a user-defined one, in VS2015 it will show it in all cases I believe).
The binding of == (i.e. which overload to call) is fixed statically at compile-time. The is nothing dynamic or virtual about it. So if you have:
public T SomeMethod<T>() where T : SomeBaseClass
{
T rv = ...;
if (rv != null)
{
then which overload of != to use will be fixed, at compile-time, with usual overload resolution (including a few special rules for ==). The rv has type T which is known to be a reference type eqaul to or deriving from SomeBaseClass. So the best overload is chosen based on that. That might be the operator !=(object, object) overload (built-in) if SomeBaseClass does not define (or "inherit") an appropriate overload.
At run-time, then, even if the actual substitution for T happens to be a more specific type SomeEqualityOverloadingClass (that satisfies the constraint of course), that does not mean a new overload resolution will happen at run-time!
This is different from the virtual method .Equals(object).
In C#, generics do not work like templates, and they are not like dynamic.
If you really want dynamic overload resolution (binding at run-time instead of at compile-time), it is allowed to say if ((dynamic)rv != null).

How to get default constructor when parameters are optional

I'm using Type.GetConstructor(Type.EmptyTypes) to get the default constructor for a class. It works if the class has a default constructor with no parameters (class A). But it doesn't work if a class has a constructor with all parameters optional (class B). Program doesn't know what the optional parameters are because it only needs the default constructor. What can statements can I use to make it work for both cases? Thanks, appreciate any help!
public class A
{
public A() {}
}
public class B
{
public B(int i = 0, string str = "") {}
}
Say I have the following class:
public class SomeClass
{
public SomeClass()
{
}
public SomeClass(int x)
{
}
public SomeClass(int x = 0, int y = 0)
{
}
}
Basically, you're asking for a query that will find the constructors that match constructor 1 and 3 above? If so, use this:
var constuctors = typeof(SomeClass).GetConstructors()
.Where(x => x.GetParameters().Count() == 0
|| x.GetParameters().Count(param => param.GetCustomAttributes(typeof(OptionalAttribute), false).Count() > 0) == x.GetParameters().Count());
Incredibly nasty query, but it gets the job done returning only 1 and 3 above.
The problem is that the C# compiler produces this:
public class B
{
// Methods
public B([Optional, DefaultParameterValue(0)] int i, [Optional, DefaultParameterValue("")] string str)
{
}
}
Something like below should work:
public static class TypeHelper {
public static ConstructorInfo GetDefaultConstructor<TType>() {
var type = typeof(TType);
return type.GetDefaultConstructor();
}
public static ConstructorInfo GetDefaultConstructor(this Type type) {
if(type == null) throw new ArgumentNullException("type");
var constructor = type.GetConstructor(Type.EmptyTypes);
if(constructor == null) {
var ctors =
from ctor in type.GetConstructors()
let prms = ctor.GetParameters()
where prms.All(p=>p.IsOptional)
orderby prms.Length
select ctor;
constructor = ctors.FirstOrDefault();
}
return constructor;
}
}
The problem is that optional parameters are nothing more than a compile time concept. You'll need to specify the constructor completely.
var ci = typeof(B).GetConstructor(new [] { typeof(int), typeof(string) });
You can write a help function that will invoke the constructor with the default values though. My example is not as robust as it should be but it should get you started.
static Func<T> CreateDefaultConstructor<T>(ConstructorInfo ci)
{
var l = new List<object>();
foreach (var p in ci.GetParameters())
{
if (p.IsOptional)
{
l.Add(p.RawDefaultValue);
}
}
return () => (T)ci.Invoke(l.ToArray());
}
The problem is that, in the case of B, it does not have a constructor with no parameters.
Optional arguments are a compile time construct - in the IL, it's a constructor with 2 parameters (which are flagged with attributes). As such, there is no default constructor as far as Reflection is concerned.
To get the one that has more optional parameters or an empty constructor at all, use:
typeof(myClass)
.GetConstructors()
.OrderBy(x => x.GetParameters().Length - x.GetParameters().Count(p => p.IsOptional))
.FirstOrDefault();
When a constructor, or any other method, has optional arguments it doesn't cause the compiler to generate multiple versions of the method. Instead it generates a single method which has all of the specified parameters. The default values are encoded in attributes attached to the method signature. These are used at the call site to make their values optional.
So here there is no default constructor but instead a single one with 2 parameters

How can I allow a method to accept either a string or int?

Using C# 4.0, is there a way to allow a method (without creating an overload) to accept a string or an int and then allow me to detect what type was passed in?
Since you're using C# 4.0, you can write a generic method. For example:
void MyMethod<T>(T param)
{
if (typeof(T) == typeof(int))
{
// the object is an int
}
else if (typeof(T) == typeof(string))
{
// the object is a string
}
}
But you should very seriously consider whether or not this is a good idea. The above example is a bit of a code smell. In fact, the whole point of generics is to be generic. If you have to special-case your code depending on the type of the object passed in, that's a sign you should be using overloading instead. That way, each method overload handles its unique case. I can't imagine any disadvantage to doing so.
Sure you can! An example of this is
public void MyMethod(object o)
{
if (o.GetType() == typeof(string))
{
//Do something if string
}
else if (o.GetType() == typeof(int))
{
// Do something else
}
}
You can wrap string and int in some wrapper with marker interface and pass them to a method.
Something like this
interface IMyWrapper<T> { T Value {get; }}
public class StringWrapper: IMyWrapper<string> { ... }
public class IntWrapper: IMyWrapper<int> { ... }
void MyMethod<T>(IMyWrapper<T> wrapper)
{
}
I would think a method overload would be a straightforward solution, if you want to stay away from stuff like reflection or checking types.
public void MethodName(string foo)
{
int bar = 0;
if(int.tryparse(foo))
return MethodName(bar);//calls int overload
}

Is it a bad thing to override == and have an instance compare equal to null?

Background
Let's say I have the following class:
public class MyValue<T>
{
public T Value { get; set; }
public static bool operator ==(MyValue<T> first, MyValue<T> second)
{
// if first and second are the same instance, they are equal
if (object.Equals(first, second))
{
return true;
}
// for each of the objects, get a value indicating whether either
// the object or its Value property is null
bool firstIsNull = object.Equals(first, null) ? true : first.Value == null;
bool secondIsNull = object.Equals(second, null) ? true : second.Value == null;
// if both are null, they are equal
if (firstIsNull && secondIsNull)
{
return true;
}
// Not both are null. If one is, they are not equal
if (firstIsNull || secondIsNull)
{
return false;
}
// Neither first nor second is null; compare their values
return first.Value.Equals(second.Value);
}
// more code implementing !=, Equals, GetHashCode, implicit conversions and so on
}
This class will be used as the type on properties in an object model. An object could look like so:
public class SomeClass
{
public SomeClass()
{
SomeValue = new MyValue<string>();
}
public MyValue<string> SomeValue { get; set; }
}
The idea with this is that the class simply represents the value of its Value property. It has some more functionality that is stripped away since it's not relevant for the question (some validation and stuff). Since the class has no value in itself, we want it to be as little intrusive as possible when used. Implicit conversions allows for code like this:
SomeClass instance = new SomeClass();
instance.SomeValue = "my string";
...and the question:
The idea with overloading the == (and !=) operator is to have an instance of the object where Value is null to compare equal to null (partly because we feel it makes sense, partly because of backwards compatibility issues in the object model):
MyValue<string> a = new MyValue<string>();
MyValue<string> b = null;
bool areTheyEqual = (a == b); // this will be true
This may of course seem a bit confusing, but given that MyClass is simply a wrapper, that in most of the code will be rather invisible, does it make sense to you too, or is it something really bad that we will regret for reasons that we overlooked?
In my opinion, == operator in C# is already confusing enough. If you overload it like that, you'll be increasing the possibility of confusion.
Class c = somethingEqualsToNullButNotNull;
if (c == null) { // true
}
object co = c;
if (co == null) { // false. WTF!?
}
You say you've already overridden Equals to provide the same behaviour. That means you've already broken the contract for Equals, which explicitly states:
- x.Equals(a null reference (Nothing in Visual Basic)) returns false.
Basically: no, don't do this. It will be confusing to users of the class.
Now Nullable<T> appears to break this rule:
int? x = new int?(); // Or int? x = null;
object o = null;
Console.WriteLine(x.Equals(o)); // True
... but in this case x isn't a reference, which is part of the contract description. The only way of making x a reference is to box the value, at which point x is null anyway. In your case, MyValue is a class so you can have a non-null reference which violates the contract.
If you override ==, then normally it is best to override .Equals to use the same logic.

Resolving a parameter name at runtime [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Finding the Variable Name passed to a Function in C#
In C#, is there a way (terser the better) to resolve the name of a parameter at runtime?
For example, in the following method, if you renamed the method parameter, you'd also have to remember to update the string literal passed to ArgumentNullException.
public void Woof(object resource)
{
if (resource == null)
{
throw new ArgumentNullException("resource");
}
// ..
}
One way:
static void Main(string[] args)
{
Console.WriteLine("Name is '{0}'", GetName(new {args}));
Console.ReadLine();
}
This code also requires a supporting function:
static string GetName<T>(T item) where T : class
{
var properties = typeof(T).GetProperties();
Enforce.That(properties.Length == 1);
return properties[0].Name;
}
Basically the code works by defining a new Anonymous Type with a single Property consisting of the parameter who's name you want. GetName() then uses reflection to extract the name of that Property.
There are more details here: http://abdullin.com/journal/2008/12/13/how-to-find-out-variable-or-parameter-name-in-c.html
Short answer: No, there isn't. (Is that terse enough? ;)
(EDIT: Justin's answer probably counts. It leaves a bad taste in my mouth, but it accomplishes the goal of "no need to put the parameter name into a string". I don't think I'd really count AOP though, as that's really changing to a completely different approach rather than answering the original question of getting a parameter name from within a method.)
Longer answer: There's a way to find out all the parameters of a method, but I don't think it's useful in this case.
Here's an example which displays the parameter names from a couple of methods:
using System;
using System.Reflection;
class Test
{
static void Main()
{
Foo(null);
Bar(null);
}
static void Foo(object resource)
{
PrintParameters(MethodBase.GetCurrentMethod());
}
static void Bar(object other)
{
PrintParameters(MethodBase.GetCurrentMethod());
}
static void PrintParameters(MethodBase method)
{
Console.WriteLine("{0}:", method.Name);
foreach (ParameterInfo parameter in method.GetParameters())
{
Console.WriteLine(" {0} {1}",
parameter.ParameterType,
parameter.Name);
}
}
}
So that does that, but if you have multiple parameters and you wanted to throw an appropriate exception, how would you know (in a safe way) which to use? Ideally you want something like:
public void Woof(object resource)
{
if (resource == null)
{
throw new ArgumentNullException(infoof(resource));
}
// ..
}
where the mythical infoof operator would return a ParameterInfo. Unfortunately this doesn't exist.
I dealt with this very same issue. There are a couple of ways of getting the parameter name but the most performant is to dip down into the IL. You can see an example of my implementation on my blog post on this very issue Taking the pain out of parameter validation.
The one caveat to this approach is you need to pass the parameter name in as a delegate but it is small price to pay for cleaner code:
public void SomeMethod(string value)
{
Validate.Argument(() => value).IsNotNull().IsNotEmpty();
}
Which is somewhat cleaner and clearer than:
public void SomeMethod(string value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
if (value == string.Empty)
{
throw new ArgumentException("Value cannot be an empty string.", "value");
}
}
The static method approach has allowed me to chain a number of methods together in a fluent interface. Initially an Argument object is returned which only allows a basic null test which returns a ReferenceArgument object which can then have additional validation. If the object under test is a value type then different tests are available.
The API allows for a number of common tests but it would be hard to capture all the possible tests so to provide flexibility a generic test method allows an expression or function to be provided and in the case of the former the expression can actually be used as the error message.
My example only covers a few of the basics but you can easily expand the interface to check for ranges and throw ArgumentOutOfRangeExceptions or test objects inherit from a specific base class or implement an interface. There are some similar implementations but I have not as yet seen any that get the parameter name.
You can get this information using AOP. You can define an intercept that is invoked before method execution and throw the exception there. This also takes care of the problem that null checking is a cross-cutting concern.
PostSharp is a good simple implementation of AOP.
Here's what your code would look like (haven't tested, but it should get you very close)
[AttributeUsage(AttributeTargets.Parameter)]
public class CanBeNullAttribute : Attribute
{
private readonly bool canBeNull;
public CanBeNullAttribute()
: this(true)
{
}
public CanBeNullAttribute(bool canBeNull)
{
this.canBeNull = canBeNull;
}
public bool AllowNull
{
get { return canBeNull; }
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class EnforceNullConstraintAttribute : OnMethodInvocationAspect
{
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
object[] arguments = eventArgs.GetArgumentArray();
ParameterInfo[] parameters = eventArgs.Delegate.Method.GetParameters();
for (int i = 0; i < arguments.Length; i++)
{
if (arguments[i] != null) continue;
foreach (CanBeNullAttribute attribute in parameters[i].GetCustomAttributes(typeof(CanBeNullAttribute), true))
{
if (!attribute.AllowNull) throw new ArgumentNullException(parameters[i].Name);
}
}
base.OnInvocation(eventArgs);
}
}
Now, you can modify your method:
[EnforceNullConstraint]
public void Woof([CanBeNull(false)] object resource)
{
// no need to check for null, PostSharp will weave it at compile time
// execute logic assured that "resource" is not null
}
You might want:
1)
public static void ThrowIfNull<T>(Expression<Func<T>> expr)
{
if (expr == null || expr.Compile()() != null) //the compile part is slow
return;
throw new ArgumentNullException(((MemberExpression)expr.Body).Member.Name);
}
or
2)
public static void ThrowIfNull<T>(Expression<Func<T>> expr)
{
if (expr == null)
return;
var param = (MemberExpression)expr.Body;
if (((FieldInfo)param.Member).GetValue(((ConstantExpression)param.Expression).Value) == null)
throw new ArgumentNullException(param.Member.Name);
}
And call it:
Class.ThrowIfNull(() => resource);
But that's not what you would want probably. Its also a lot slower 1) is abt 1000 times slower than 2). May be:
3)
public static void ThrowIfNull<T>(this T item) where T : class
{
if (item == null)
return;
var param = typeof(T).GetProperties()[0];
if (param.GetValue(item, null) == null)
throw new ArgumentNullException(param.Name);
}
And call it:
new { resource }.ThrowIfNull();
Cleaner, much faster than above 2! :)
You can also extend these methods for properties of objects. For eg.,
new { myClass.MyProperty1 }.ThrowIfNull();
You can cache property values to improve performance further as property names don't change during runtime. See related question Finding the variable name passed to a function

Categories