My question is, I think, perfectly illustrated by the following code (
which does not compile as it stands):
public abstract class MyBaseBusinessObjectClass
{
public abstract string BusinessObjectName { get; }
}
public class BusinessObjectOne : MyBaseBusinessObjectClass
{
public override string BusinessObjectName => "One";
public string FunctionSpecificToOne => "1";
}
public class BusinessObjectTwo : MyBaseBusinessObjectClass
{
public override string BusinessObjectName => "Two";
public string FunctionSpecificToTwo => "2";
}
public abstract class MyBaseLogicClass
{
public abstract void PrintParamName<T>( T param );
}
public class LogicHandlingOnes : MyBaseLogicClass
{
public override void PrintParamName<BusinessObjectOne>( BusinessObjectOne param )
{
Console.WriteLine( $"BusinessObjectOne.PrintParamName() returned '{param.BusinessObjectName}'." );
string s = ((BusinessObjectOne)param).FunctionSpecificToOne();
}
}
public class LogicHandlingTwo : MyBaseLogicClass
{
public override void PrintParamName<BusinessObjectTwo>( BusinessObjectTwo param )
{
Console.WriteLine( $"BusinessObjectTwo.PrintParamName() returned '{param.BusinessObjectName}'." );
string s = ((BusinessObjectTwo)param).FunctionSpecificToTwo();
}
}
This gives the following errors on compilation:
1>Program.cs(35,77,35,95): error CS1061: 'BusinessObjectOne' does not contain a definition for 'BusinessObjectName' and no accessible extension method 'BusinessObjectName' accepting a first argument of type 'BusinessObjectOne' could be found (are you missing a using directive or an assembly reference?)
1>Program.cs(47,77,47,95): error CS1061: 'BusinessObjectTwo' does not contain a definition for 'BusinessObjectName' and no accessible extension method 'BusinessObjectName' accepting a first argument of type 'BusinessObjectTwo' could be found (are you missing a using directive or an assembly reference?)
1>Program.cs(38,42,38,63): error CS1061: 'BusinessObjectOne' does not contain a definition for 'FunctionSpecificToOne' and no accessible extension method 'FunctionSpecificToOne' accepting a first argument of type 'BusinessObjectOne' could be found (are you missing a using directive or an assembly reference?)
1>Program.cs(50,42,50,63): error CS1061: 'BusinessObjectTwo' does not contain a definition for 'FunctionSpecificToTwo' and no accessible extension method 'FunctionSpecificToTwo' accepting a first argument of type 'BusinessObjectTwo' could be found (are you missing a using directive or an assembly reference?)
If I stick with the version of the code with the constrained parameter, as shown below, it compiles fine if I comment out the two lines that attempt to cast the parameters to their derived types.
I am obviously failing to understand something fundamental about generic parameters but it is the compiler message that confuses me. It uses the 'correct' derived type in the message and then tells me it can't find the function contained in that class.
Is there something simple I'm not getting here or do I need to find my 'Beginning C#' book?
I would also appreciate more general comments on the architecture. I am aware it is less than ideal but the real code is too big to refactor before my next delivery deadline so I just need to get something working for now.
What I have tried:
I have tried constraining the generic type as follows:
public abstract class MyBaseLogicClass
{
public abstract void PrintParamName<T>( T param ) where T : MyBaseBusinessObjectClass;
}
Which gets rid of two errors but leaves:
1>------ Build started: Project: ConsoleApp1, Configuration: Debug Any CPU ------
1>Program.cs(38,42,38,63): error CS1061: 'BusinessObjectOne' does not contain a definition for 'FunctionSpecificToOne' and no accessible extension method 'FunctionSpecificToOne' accepting a first argument of type 'BusinessObjectOne' could be found (are you missing a using directive or an assembly reference?)
1>Program.cs(50,42,50,63): error CS1061: 'BusinessObjectTwo' does not contain a definition for 'FunctionSpecificToTwo' and no accessible extension method 'FunctionSpecificToTwo' accepting a first argument of type 'BusinessObjectTwo' could be found (are you missing a using directive or an assembly reference?)