Reputation: 1863
I am trying to create a generic mapping function that will take in various types that all inherit from NSReportBase and then new up the appropriate object and return it. So far, I have the following:
internal static T BuildNamingStandardType<T>(DataRow dr) where T : NSReportBase, new()
{
T newNamingStandardReport = null;
if (typeof(T) is NSPipelineSystems)
newNamingStandardReport = new NSPipelineSystems(dr["Column1"], dr["Column2"]);
else if (typeof(T) is NSPipelineSegmentGroups)
newNamingStandardReport = new NSPipelineSegmentGroups(dr["Column3"]);
return newNamingStandardReport;
}
However, I am getting an error that each concrete type cannot be implicitly converted to type 'T'. Given that T is known by the compiler to be of type 'NSReportBase', I am not sure I understand the issue here, let alone how to fix it.
EDIT: I may have over simplified the example. The challenge is that the constructors do not actually take no arguments, but different numbers and types of columns from the DataRow that is a parameter to the method. I know that I could do this polymorphically, but I would like to avoid exposing the DataRow column names to my business logic by moving this method into the respective domain objects.
Upvotes: 1
Views: 184
Reputation: 171206
Given that T is known by the compiler to be of type 'NSReportBase'
It is not known to the compiler. The C# language does not define that the compiler must derive types through data-flow tracing (in fact it is forbidden to compile this). Humans can see this fact, the language is defined not to see it (but tools like Resharper can see it as a utility).
Solution: First cast to object
, then to the concrete type. This method still feels like a hack to me. Maybe you should evaluate whether you should use generics in the first place. The purpose of generics is that your generic method does not need to care about the concrete type.
Upvotes: 1
Reputation: 37780
internal static T BuildNamingStandardType<T>(DataRow dr) where T : NSReportBase, new()
{
return new T();
}
But it isn't clear, why there's a dr
parameter.
Upvotes: 0
Reputation: 1098
As long as the type your trying to instantiate has a default constructor you could use the new constraint.
where T : new()
then you are able to
var instance = new T();
Also the error comes from the fact that the Compiler only knows that T is of Type NSReportBase
but when using T becomes either NSPipelineSystems
or NSPipelineSegmentGroups
and you cannot assign NSPipelineSystems
to NSPipelineSegmentGroups
or vice versa, this is why you get that error.
If you want to solve that you have to change
T newNamingStandardReport = null;
to
NSReportBase newNamingStandardReport = null;
and cast the return value manually to (T).
Upvotes: 2