0

I have a method that is passing in a object as a generic. Note that these objects do not derive from the same class. I have a function that I would like to call regardless of the type but am not able to call because it cannot determine the type.

'T' does not contain a definition for 'Validate'

And the code

public void VerifyInput<T>(T obj)
{
    ((T)obj).Validate();
}

This is being used to validate user data passed in. Each of the classes are responsible for setting their own validation but they are not necessarily related in any way. I have simplified this but the basic question remains. How can I cast the type of a generic to call an object method?

McArthey
  • 1,614
  • 30
  • 62
  • You can't do this unless your classes derive from the same base class containing the `Validate` method or implement an interface with this method. Then you could constrain the T generic parameter to this base class or interface. – Darin Dimitrov Sep 23 '16 at 17:11
  • This is not possible in C# unless you specify an interface with the method `Validate` and then checks upon the generic type like "where T : IValidate` where `IValidate` is the interface with the method. Another way to do it without that is using reflection, but it's expensive. – Bauss Sep 23 '16 at 17:11
  • Thanks. I was going to add that I was aware of generic constraints but was hoping I could perform this without it. I appreciate the update. – McArthey Sep 23 '16 at 17:11
  • If you want to get wacky you could cast it to a dynamic and call Validate(), that would actually work, but be quite bad, the interface idea is much better. – gmn Sep 23 '16 at 17:16
  • See the marked duplicate for the general solution. Just declare the interface with your method, instead of a property as seen in the answer there. See also e.g. https://stackoverflow.com/questions/33542719/call-method-on-parameter-of-generic-type and https://stackoverflow.com/questions/622264/what-does-where-t-somevalue-mean – Peter Duniho Sep 23 '16 at 17:59

2 Answers2

2

Create an interface IValidatable with the Validate() method on there, implement it in each class and change the input of VerifyInput to take that interface and get rid of the generic types.

public void VerifyInput(IValidatable obj)
{
    obj.Validate();
}

In fact you may be able to get rid of VerifyInput completely if you do this and just call validate on the target objects.

gmn
  • 4,199
  • 4
  • 24
  • 46
2

Note that these objects do not derive from the same class. I have a function that I would like to call regardless of the type but am not able to call because it cannot determine the type.

This is where you should be using an interface.

public interface IValidatable {
  void Validate();
}

And on your method

public void VerifyInput<T>(T obj) where T : IValidatable
{ 
  obj.Validate();
}

Doing this will ensure that the passed in type conforms to the interface contract but not restrict it to a specific type definition.

Igor
  • 60,821
  • 10
  • 100
  • 175