Reputation: 4178
I have a method that I overload on a concrete type and tag for compile time failure on generic types (using [ObsoleteAttribute]
).
The reason of doing do is to make sure any caller to the method specializes it for the target type. There is no way to change the actual types or their hierarchy; so I need to use have ad-hoc methods to achieve this goal (static void CustomMethod
below).
Here is a sample code:
class Program
{
class MyClass { }
static void CustomMethod(MyClass m)
{
Console.WriteLine("m");
}
[ObsoleteAttribute("Unknown type", true)]
static void CustomMethod<T>(T m)
{
;
}
static void Invoke<T>(T input)
{
CustomMethod(input);
}
static void Main(string[] args)
{
// This should compile ok
MyClass m = new MyClass();
Invoke(m);
// This should fail compilation
Invoke("no CustomMethod() defined for me");
}
}
This fails with Error CS0619 'Program.CustomMethod<T>(T)' is obsolete: 'Unknown type'
This is easily achievable with C++ templates since the compiler only resolves invocation to the actual instantiated type and not any generic type T
Is there any "compile time" way to make the Invoke<T>()
work?
Note: not looking for solutions using C# dynamic
or reflection.
Upvotes: 2
Views: 123
Reputation: 39085
Within the constraints you outlined, you really don't have any options other than creating separate Invoke
overloads for each type you want a CustomMethod
for.
Assuming Invoke
does more than simply calling CustomMethod
, you can avoid repeating that common code by creating child classes that wrap the CustomMethod
, and handling the common stuff in the base class:
class Program
{
class MyClass { }
class MyClass2 { }
// wrapper classes for CustomMethod for each type
class MyClassStrategy : Strategy<MyClass>
{
protected override void CustomMethod(MyClass t)
{
Console.WriteLine("MyClass");
}
}
class MyClass2Strategy : Strategy<MyClass2>
{
protected override void CustomMethod(MyClass2 t)
{
Console.WriteLine("MyClass2");
}
}
// base class for doing "common stuff"
abstract class Strategy<T>
{
protected abstract void CustomMethod(T t);
public virtual void Run(T t)
{
// do common stuff...
CustomMethod(t);
// do more common stuff...
}
}
// create an Invoke overload for each wrapper class
static void Invoke(MyClass m) { new MyClassStrategy().Run(m); }
static void Invoke(MyClass2 m2) { new MyClass2Strategy().Run(m2); }
static void Main(string[] args)
{
// These compile OK:
MyClass m = new MyClass();
Invoke(m);
MyClass2 m2 = new MyClass2();
Invoke(m2);
// This doesn't compile:
// (obviously, there are no Invoke overloads that take a string)
Invoke("sdfdsff");
}
}
Upvotes: 1