Type parameter 'T' has the same name as the type parameter from outer type '...'

18,917

Solution 1

You can do one of two things:

  1. Ignore the warning and make both types T.
  2. Do a run-time check and throw an exception:

    if (typeof(T) != typeof(U)) throw Exception("Not the same type");
    

As others have stated, perhaps you need to rethink the way you are designing your interfaces.

Solution 2

The biggest problem is that your interfaces are not well defined, and do not match the intent of your code.

If your T is not publicly visible on the interface, then external code doesn't even have to know there is a T. You need to either make methods that receive or return T, or have some property of type T, or you should simply get rid of T entirely, and make your interfaces non-generic.

Once you shore this up, it should become more obvious why you don't need two different interfaces here, and you should no longer have to reconcile them.

If it turns out that you do need a version that takes T, and a non-T version, then the more idiomatic way to do this is pass around object instead of T:

public interface IFoo
{
    void DoSomething(object o);
    object DoSomethingElse();
}

public interface IFoo<T>
{
    void DoSomething(T item);
    T DoSomethingElse();
}

See interfaces like IEnumerable, ICollection, IList, etc for examples of this.

But consider carefully. This last design compromise (having both a generic and object version) always leaves something to be desired.

You'll sacrifice one of these:

  • Good interface design that directly communicates a design contract (If you throw exceptions or do a no-op when the wrong type is passed in)
  • Type safety, and the reduction in bugs that goes with it (if you correctly operate on any-old-object)

Solution 3

Just try

void IFoobar.Foo<U>(int x) { Foo(x); }

Of course, that still doesn't guarantee that U is the same as T. You can't enforce that at compile-time, because when you're implementing an interface, you must follow its rules -- and IFoobar doesn't put such a restriction on Foo<T>, and if you do, you would no longer be implementing the interface (by definition, since you are being stricter, and yet you're claiming that you're not).

You can try checking it at run time instead, although that's somewhat "cheating" (since you're not really conforming to the interface then either).

Share:
18,917
michael
Author by

michael

Updated on June 11, 2022

Comments

  • michael
    michael almost 2 years
    public abstract class EntityBase { ... }
    
    public interface IFoobar
    {
        void Foo<T>(int x)
            where T : EntityBase, new();
    }
    
    public interface IFoobar<T>
        where T : EntityBase, new()
    {
        void Foo(int x);
    }
    
    public class Foobar<T> : IFoobar, IFoobar<T>
        where T : EntityBase, new()
    {
        public void Foo(int x) { ... }
    
        void IFoobar.Foo<T>(int x) { Foo(x); }
    }
    

    I get a compiler warning: Type parameter 'T' has the same name as the type parameter from outer type '...'

    I tried doing: void IFoobar.Foo<U>(int x) { Foo(x); }, however then I can't guarantee that U and T are the same. The way that the Foobar class is implemented, it is very important that they be the same.

    I also tried doing: void IFoobar.Foo<U>(int x) where U : T { Foo(x); }, however that does not guarantee that U and T are equal and it does not allow me to redefine the constraint since it was defined on the interface.

  • Ken Wayne VanderLinde
    Ken Wayne VanderLinde almost 13 years
    While that maintains the constraint on the type, it does not guarantee that T and U are the same.
  • michael
    michael almost 13 years
    That doesn't guarantee that U is equal to T, and I can't redefine the constraints on U since they were defined in the interface.
  • Merlyn Morgan-Graham
    Merlyn Morgan-Graham almost 13 years
    This will not compile. Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly. Remove the where clause to fix this.
  • user541686
    user541686 almost 13 years
    @Merlyn: Whoops my bad, fixed.
  • Merlyn Morgan-Graham
    Merlyn Morgan-Graham almost 13 years
    +1; Your last points about interface design and runtime checks are the same issues as when accepting object. You're basically throwing out type safety. In this case, it is even worse, because it looks type-safe on the surface.