2

I am using Nsubstitute for mocking. To reduce code I want to write a generic class that fakes a generic attribute:

public class Tester<TValue>
    where TValue: IValue
{
    // this is used inside the class in other methods
    private TValue CreateValue()
    {
        return Substitute.For<TValue>(); // here the compiler has an error
    }
}

This code gives a compile error at the marked place:

The type 'TValue' must be a reference type in order to use it as parameter 'T' in the generic type or method 'Substitute.For(params object[])'

This seems obvious, because the implementation of the Substituteclass looks like this:

public static class Substitute
{
    public static T For<T>(params object[] constructorArguments) where T : class;
}

What I am wondering about is, why then such a code is possible: Substitute.For<IValue>() and does not raise an error. Can anybody explain how to do the generic class with the faking right?

scher
  • 1,813
  • 2
  • 18
  • 39

1 Answers1

1

The below code should work:

public class Tester<TValue>
    where TValue : class, IValue
{
    // this is used inside the class in other methods
    private TValue CreateValue()
    {
        return Substitute.For<TValue>(); // here the compiler has an error
    }
}

The type must be a reference type in order to use it as parameter 'T' in the generic type or method may be worth a read.

The reason it is necessary is that Substitute.For specifies a reference type (class). Thus, any generic callers to it (like yourself) need to specify the same class constraint.

mjwills
  • 23,389
  • 6
  • 40
  • 63
  • Thanks for your response. I have seen the constraint, that NSubstitute needs a class as generic parameter. I wondered, that it is possible to use an interface with `Substitute.For()`. For my case it is not possible to constraint the `TValue` generic parameter to a class, as I need it for interfaces. – scher Jul 20 '17 at 05:06
  • Can you update your post with your interface definition (i.e. file) for `IValue`, and also the files for every class / struct that implements `IValue`? – mjwills Jul 20 '17 at 05:14
  • Note that `class` in the context of my code sample doesn't mean "class rather than interface" it means "class rather than struct". Did you try my above code for your purposes? Did it work? – mjwills Jul 20 '17 at 05:15
  • The note about the keyword `class` opened my eyes. Yesterday I tried to manage it with the class constraint and it didn`t work. Today everything is fine. Maybe it was something else. Thank you very much. You are great. – scher Jul 20 '17 at 05:23