Jamie Marshall
Jamie Marshall

Reputation: 2304

Interface that declares an object type

This may be a question about fundamental design.

I want to perform an operation on a mystery object, as long as it implements my interface IMyInterface. And I want one of methods defined by the interace to return an instance of mystery object so...

IMyInterface
  {
    object GetInstance();
  }

public class MysteryObject : IMYInterface
}
  public object GetInstance()
    {
      MysteryObject instance = new MysteryObject();
      return instance;
    }
}

but this results in unnecessary 'object' types and the overhead associated with those. C# specifically kills this overhead with the use of generic types. It would be ideal to do something like this:

IMyInterface
  {
    T GetInstance<T>();
  }

public class MysteryObject : IMYInterface
}
  public MysteryObject GetInstance<MysteryObject>()
    {
      MysteryObject instance = new MysteryObject();
      return instance;
    }
}

I know this second example doesn't work. I know the syntax is wrong. ..but I'm wondering if there is a better way to require that an object that implements IMyInterface return an instance of it's own type.

My examples a little weird but i think most will understand the sentiment. Strangely, I've found very little examples or questions around this.

Upvotes: 2

Views: 70

Answers (2)

Deadzone
Deadzone

Reputation: 814

You can just make the return type IMyInterface:

public interface IMyInterface
{
    IMyInterface GetInstance();
}

public class MysteryObject : IMyInterface
{
    public IMyInterface GetInstance()
    {
        MysteryObject instance = new MysteryObject();
        return instance;
    }
}

Or with generics:

public interface IMyInterface<T>
{
    T GetInstance();
}

public class MysteryObject : IMyInterface<MysteryObject>
{
    public MysteryObject GetInstance()
    {
        MysteryObject instance = new MysteryObject();
        return instance;
    }
}

If you want the generic argument to be of type IMyInterface you add constraint like this:

public interface IMyInterface<T>
    where T : IMyInterface<T>
{
    T GetInstance();
}

Update

Here are some example usages to see what the difference between these 2 versions is:

  1. Returning interface IMyInterface:

    IMyInterface a = new MysteryObject().GetInstance(); // valid 
    MysteryObject b = new MysteryObject().GetInstance();// invalid 
    MysteryObject b = (MysteryObject)new MysteryObject().GetInstance(); // valid
    
  2. Returning the generic type argument from the interface:

    IMyInterface<MysteryObject> a = new MysteryObject().GetInstance(); //valid
    MysteryObject b = new MysteryObject().GetInstance(); //valid
    

Upvotes: 4

BradleyDotNET
BradleyDotNET

Reputation: 61349

You almost have it. You need to make the whole interface generic:

IMyInterface<T>
  {
    T GetInstance();
  }

public class MysteryObject : IMYInterface<MysteryObject>
}
  public MysteryObject GetInstance()
    {
      MysteryObject instance = new MysteryObject();
      return instance;
    }
}

Upvotes: 2

Related Questions