I have written a generic class
class MyClass : MyClass<string> { } //this line is in error
class MyClass<OutputBaseType> : MyClass<OutputBaseType, List<OutputBaseType>>
where OutputBaseType : new() //this new constraint is needed
{}
class MyClass<OutputBaseType,OutputType>
where OutputType : ICollection<OutputBaseType>, new()
where OutputBaseType : new()
{
public void Method(OutputBaseType z)
{
if (z!=null) { ... }
}
...
}
Because string has no default constructor the first line will now work. If I remove this line and modify clients to explicitly define string, then it does not work for the same reason.
If I remove where OutputBaseType : new() and the other new() then it works with OutputBaseType of string but not with OutputType of dictionary<...>. This is because KeyValuePair<> used by dictionary is a struct not a class, so can not be null. (I don’t like null usually but need it here)
Is there a way to get this to work?
Amendments:
I have removed new constraint on OutputBaseType.
Then replaced assigning of null and assigning with default construction, with default(OutputBaseType)
This looks promising but I now have an error in the condition expression on line
OutputBaseType outputItem = ...;
if (outputItem != default(OutputBaseType)) { _Output.Add(outputItem); }
The error is:
Operator '!=' cannot be applied to operands of type 'OutputBaseType' and 'OutputBaseType'
You can simply use
default(T)instead ofnullfor value types. The default constructor of value types cannot be user defined, and always initializes all fields to their default value (0,null,…). So you don’t need thenew()constraint if you just usedefault(T)instead ofnew T(), since for value types they are equivalent, and for reference types you wantnullwhich happens to be thedefaultof any reference type.==is not available on generic types. You can either useobject.Equals(this causes boxing) orEqualityComparer<T>.Default.Equals. I prefer the second one: