1

The code below is valid:

public class Converter<T,M> : CustomCreationConverter<M>  
    where T : new()
    where M : class

However, this is what I would like to do:

public class Converter<T,M> : CustomCreationConverter<M>  
    where T : new()
    where M : interface

Is something equivalent to this possible?

A constraint that specified that T could be cast as M would also suffice in my specific circumstance.

To clarify, I am not looking for the ability to make T implement some specific interface.

Someone may try to mark this question as a duplicate of "Force generic interface implementation in C#". Here are the reasons why I believe it is worth not marking my question a duplicate:

  1. That question is over 8 years old
  2. The question was resolved when the person posting an answer discovered that the person posting the question actually wanted to know how to implement a specific interface
  3. If this is not possible through constraints, there may be a workaround

The reason I'm trying to do this is because I'm trying to create multiple custom JSON converters using Json.NET's JsonConverter Class.

public class Converter<T,M> : CustomCreationConverter<M>  
    where T : new()
{
    public override bool CanRead => base.CanRead;

    public override bool CanWrite => base.CanWrite;

    public override bool CanConvert(System.Type objectType)
    {
        return base.CanConvert(objectType);
    }

    public override M Create(System.Type objectType)
    {
        return new T(); //Cannot implicity convert type 'T' to 'M'
    }

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }

    public override object ReadJson(JsonReader reader, System.Type objectType, object existingValue, JsonSerializer serializer)
    {
        return base.ReadJson(reader, objectType, existingValue, serializer);
    }

    public override string ToString()
    {
        return base.ToString();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        base.WriteJson(writer, value, serializer);
    }
}

I could do the above or public class MyClassConverter : CustomCreationConverter<IMyClass>{} for every class I need a converter for. Just trying to keep things DRY!

cOborski
  • 134
  • 1
  • 15
  • 6
    Why does it matter if the type is a class or an interface? What I mean by the question is that knowing why it matters might tell us what you're hoping to accomplish using that knowledge, and we might be in a better position to suggest appropriate alternatives. – Lasse V. Karlsen Jul 23 '19 at 16:17
  • 1
    Contraints in generic are meant to achieve a functionality, how does it matter where they come from till the point rules are obeyed. You haven't explained what specific thing which an interface achieve in your case – Mrinal Kamboj Jul 23 '19 at 16:18

2 Answers2

2

A constraint that specified that T could be cast as M would also suffice in my specific circumstance.

It is possible to make a constraint where T must be derived from the type specified by another argument.

where T : M
  • Thanks, you're right. Also, in case anyone else stumbles across this, this information can be found at https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters. I found it just after you answered. – cOborski Jul 23 '19 at 16:38
  • This doesn't answer the question you have asked, with this kind of generic constraint how would you ensure M is always an interface thus T is always an interface. Generics always remain compile time verification, so nothing new will happen over run-time – Mrinal Kamboj Jul 24 '19 at 03:17
  • @MrinalKamboj I didn't ask that T always be an interface, just that it implements M. M is what I wanted to be an interface. This answer requires that T be an implementation of M, meaning that M must be an interface or a base class. You are correct that this "doesn't answer the question" because it doesn't specifically force M to be an interface, but it would be useful for anyone else wanting the answer to this question. – cOborski Jul 25 '19 at 01:05
  • Your assumption is incorrect here M needn't be an interface / base class, it can also be same class a T when it comes to generic constraints, thus the issue remains as is you cannot guarantee its anything base. This means T and M can be same class and code will not complain – Mrinal Kamboj Jul 25 '19 at 12:43
0

The documentation on the where generic type constraint tells you which constraints you can specify.

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value or unmanaged type. They declare capabilities that the type argument must possess.

Given that, I believe the answer to your question is no, there is no way to specific that a generic type parameter be any interface.

Joshua Robinson
  • 3,399
  • 7
  • 22
  • Thanks, I did read the documentation before posting. Microsoft's documentation isn't always comprehensive, though. – cOborski Jul 23 '19 at 16:29
  • Documentation is indeed clear, it clearly states what can comprise of a constraint and since there's no way to define "any interface", so there's no way to use it – Mrinal Kamboj Jul 24 '19 at 03:22
  • @MrinalKamboj The linked documentation is not a comprehensive list of possible constraints. – cOborski Jul 25 '19 at 01:10