Robin Luiten
Robin Luiten

Reputation: 5328

VS2010 compiler error "is not assignable to parameter type T" not a constraint issue I believe

I don't think its a Rhino mocks related.

Is it a compiler bug ?

The line in 2nd block of code below the ERROR: comment is giving the compiler warning, and I dont understand why. What surprised me even more was that block 3 works.

This one works fine, so i converted it to Generic ActivatePresenterAction2

private void ActivatePresenterAction1(IListViewHelper<PairDirEntry> lvh)
{
    var args = lvh.GetArgumentsForCallsMadeOn(
            x => x.ActionOnActivateItem(Arg<Action<PairDirEntry>>.Is.Anything));
    Assert.That(args.Count, Is.EqualTo(1));
    Assert.That(args[0].Length, Is.EqualTo(1));
    var action = (Action<PairDirEntry>)(args[0][0]); // extract the ActivateOnItem action 
    action(_pairDirEntry); // as if ActionOnActivateItem()
}

This one works fails to compile on commented line

private void ActivatePresenterAction2<T>(IListViewHelper<T> lvh) where T : class
{
    var args = lvh.GetArgumentsForCallsMadeOn(
            x => x.ActionOnActivateItem(Arg<Action<T>>.Is.Anything));
    Assert.That(args.Count, Is.EqualTo(1));
    Assert.That(args[0].Length, Is.EqualTo(1));
    var action = (Action<T>)(args[0][0]); // extract the ActivateOnItem action 
    // 
    // ERROR: is not assignable to parameter type T on hliighted line
    // marking the parameter _pairDirEntry
    // 
    action(_pairDirEntry); // as if ActionOnActivateItem()
}

This change to the generic works fine.

ActivatePresenterAction3(_stubSearchResultListViewHelper)(_pairDirEntry);

private Action<T> ActivatePresenterAction3<T>(IListViewHelper<T> lvh) where T : class
{
    var args = lvh.GetArgumentsForCallsMadeOn(
            x => x.ActionOnActivateItem(Arg<Action<T>>.Is.Anything));
    Assert.That(args.Count, Is.EqualTo(1));
    Assert.That(args[0].Length, Is.EqualTo(1));
    return (Action<T>)(args[0][0]);
}

Upvotes: 1

Views: 3617

Answers (2)

phoog
phoog

Reputation: 43056

To provide some more detail to SLaks's answer, consider this class:

class C<T>
{
    private T t; //assume that this gets assigned somehow
    private void M<T>(Action<T> action)
    {
        action(this.t);
    }
}

That won't compile because the T parameter of the method hides the T parameter of the class. They do not refer to the same type, even though they have the same name. The type of the action's argument is not the same type as the field t.

This can be corrected by removing the type parameter from the method:

class C<T>
{
    private T t; //assume that this gets assigned somehow
    private void M(Action<T> action)
    {
        action(this.t);
    }
}

Now, the action's argument is of the same type as the field t.

Upvotes: 2

SLaks
SLaks

Reputation: 888107

As the compiler error clearly states, _pairDirEntry isn't a T, so you can't pass it to a delegate that takes a T.

Upvotes: 2

Related Questions