2

I have the following code:

interface IConverter<T, U>
{
    U Convert(T obj);
}

interface IBusinessEntityConveter<T, U> : IConverter<T, U>
    where U : BusinessEntity
{
}

class LookupConveter<B> : IBusinessEntityConveter<Lookup, B>, IConverter<Lookup, Moniker>
    where B : BusinessEntity, new()
{

    #region IConverter<Lookup, Moniker> Members

    public Moniker Convert(Lookup obj)
    {
       //...
    }

    #endregion


    #region IConverter<Lookup,B> Members

    public B Convert(Lookup obj)
    {
       //...
    }

    #endregion
}

I am getting this error:

Error 2 'Convertors.LookupConveter<B>' cannot implement both 'Convertors.IConverter<Microsoft.Crm.Sdk.Lookup,B>' and 'Convertors.IConverter<Microsoft.Crm.Sdk.Lookup,Microsoft.Crm.Sdk.Moniker>' because they may unify for some type parameter substitutions

Is there a way to specify that T isn't a business entity?

AakashM
  • 62,551
  • 17
  • 151
  • 186
the_drow
  • 18,571
  • 25
  • 126
  • 193
  • You are breaking rule #1 of overloading, you cant overload methods just based on the return type. This fails long before the generics issue. – leppie Oct 18 '10 at 13:38
  • @Ieppie: What? What does that have to do with the error message? – Timwi Oct 18 '10 at 13:39
  • @Timwi: Even if you could fudge the generics issue, it will still fail due to 'broken' overload. – leppie Oct 18 '10 at 13:39
  • Even if there was a way to specify that `T` isn’t a `BusinessEntity`, you would still have the problem. The problem is that I could declare a `LookupConverter` and then that would have to implement two copies of `IConverter`, which would make the class’s behaviour ambiguous. – Timwi Oct 18 '10 at 13:40
  • @Timwi: I do not disagree with you. Just pointing out the obvious error with the overload being broken. Why the compiler is not stabbing the user, is beyond me. – leppie Oct 18 '10 at 13:42
  • @Ieppie: It’s because you got the causality the wrong way around. The overload issue is a consequence of the generics problem, not the other way around. (P.S. the previous comment was intended for the OP) – Timwi Oct 18 '10 at 13:47
  • 1
    The overload issue could be addressed by explicitly implementing one of the interfaces. If that is acceptable, then it is a non-issue. – Dr. Wily's Apprentice Oct 18 '10 at 15:06

2 Answers2

7

Nope, I'm afraid not. The only options you have are listed here Constraints on Type Parameters. In summary these are:

  • enforce a value type
  • enforce a reference type
  • enforce a non reference type, which contains no reference types
  • enforce a public parameterless constructor
  • enforce a specific base class
  • enforce a specific interface
  • enforce type derives from an argument
Ian
  • 33,605
  • 26
  • 118
  • 198
4

No, there are no "negative" constraints.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • How would you go around this unability to express resolvance of conflicgs? – the_drow Oct 18 '10 at 13:34
  • @the_drow: It's hard to say without knowing why you want the same type to convert generically and the specific type. – Jon Skeet Oct 18 '10 at 13:51
  • A lookup is a type/id tuple that represents a record in the database, converting it to a real type involves accessing a web service and fetching an xml file that is serialized to a DynamicEntity, I then convert the DynamicEntity (which is a BusinessEntity) to a home-coocked strong type. A lookup can also be converted to a moniker which is practically the same as a lookup but with less features and it is used somewhere else in the system and thus I would like to convert it easily. **This is not my code, it's Microsoft Dynamics CRM shitty architecture.** Only the converters are mine. – the_drow Oct 18 '10 at 15:59
  • @the_drow: Which bit is forcing you to implement both interfaces in the same class though? – Jon Skeet Oct 18 '10 at 16:00
  • Because they are related, I am trying to have this kind of syntax that could be injected with an IOC container: `IConverter converter = new LookupConverter()`. You might be correct though, I just tried to stick with DRY principle. If only I could specialize a generic class... – the_drow Oct 18 '10 at 16:04
  • @Jon Skeet: Would you say that specifying that T is not U is an important feature? Should I go an ask for it in Microsoft Connect? Also got any idea to resolve this issue? Should I just go with separate classes? – the_drow Oct 19 '10 at 06:25
  • 1
    @the_drow: No, I don't think it's an important feature - it would add significant complexity with only very rare benefits, IMO. And yes, just go with separate classes. – Jon Skeet Oct 19 '10 at 06:30