8

In C#, is it possible to write something like this:

public class MyClass<T> : T 
    where T : class, new() 
{
}

I know that the above implementation does not compile, but what I am actually trying to achive is implementing some kind of generic wrapper to an unknown type, so that an client can call the wrapper just as he would call the type, provided by the parameter T, instead of calling it using something like wrapper.Instance.SomeMember().

Thanks in advance!

7
  • 2
    So if you had class Foo { public string A; } you want to be able to do something like MyClass<Foo>.A? Commented Jan 25, 2013 at 10:52
  • I understand :) is there any reason why you would like to do that instead of MyClass<Foo>.Instance.A out of curiosity? Commented Jan 25, 2013 at 10:56
  • Couldn't Monads suit your needs ? mikehadlow.blogspot.fr/2011/01/… Commented Jan 25, 2013 at 11:00
  • @LukeHennerley: I want to make this class to manage instances of objects of type T, so that the client does not need to take care of when the instances need to be created. In an unmanaged world you would talk of something like an intelligent pointer. I think in C++ the behaviour I need can be achived by overloading the this-> operator, returning the contained instance. Commented Jan 25, 2013 at 11:07
  • Exact duplicate of stackoverflow.com/questions/3047830/… and stackoverflow.com/questions/1420581/… Commented Jan 25, 2013 at 11:10

2 Answers 2

5

This isn't possible.

In my opinion, I don't think that a wrapper should be implemented using inheritance.

For example, let's say we've an Engine class and you need to implement a FerrariEngine. And you have a Car class.

You're saying that Car should inherit FerrariEngine. It looks terrible for me!

At the end of the day, you're looking to do something like dependency injection using inheritance and, again, this isn't the right path.

My suggestion is don't try to make your life easier: decide an architecture based on rational points.

UPDATE

The OP said in some comment:

I want to make this class to manage instances of objects of type T, so that the client does not need to take care of when the instances need to be created.

You don't need to make strange things to get what you want:

public interface IEngine 
{
     void Start();
}

public sealed class FerrariEngine : IEngine
{
     public FerrariEngine()
     {
          Start();
     }

     public void Start()
     {
     }
}

public abstract class Car<TEngine> where TEngine: IEngine, new()
{
    public Car()
    {
        _engine = new Lazy<TEngine>(() => new TEngine());
    }

    private readonly Lazy<TEngine> _engine;

    public TEngine Engine
    {
        get { return _engine.Value; }
    }
}

public class FerrariCar : Car<FerrariEngine>
{
}

Finally, if we create an instance of FerrariCar:

Car<FerrariEngine> myFerrari = new FerrariCar();

The engine will be instantiated and started, without developer intervention!

Check how Lazy<T> and basic generic constraints make the job ;)

In summary:

  • Using Lazy<T> the engine will be instantiated only when some access the Engine property.
  • Once the lazy-loaded engine is instantiated, since FerrariEngine implements a parameterless constructor calling Start() itself, it will start the engine.

I believe that this sample illustrates you how you can get what you're looking for and using C# "as is"!

Sign up to request clarification or add additional context in comments.

5 Comments

Exactly, because the relation between Car and Engine is not like a Car is an Eingine, it is more like a Car contains an Engine and you do need to know which eninge. That's why I am asking for 'something like'. I am not looking for a solution that is based on inheritance, I was just asking if it is possible at all, and if so, how. ;)
There are situations where it's useful for a class to take an object and wrap it in such a way as to expose most of the underlying behavior, but change some slight aspect. For example, one may wish to pass a Stream to a StreamReader but have it remain useful after the StreamReader is done with it. At present, doing that requires either using boilerplate code to forward almost all members of the wrapper to corresponding members of the wrapped object, or else perhaps using something like Castle Dynamic Proxy; language support would seem more elegant (but doesn't as yet exist).
@supercat You're right. But I prefer to give the "official version" without reflection emit because I believe that the main problem of the OP was more about how to initialize associated objects without the intervention of the caller/developer.
Even though this does not realy solve my problem, the answer answers my question, describes why my problem cannot be solved the way I want to do it and suggests an alternative. Thank you for this :-)
@Aschratt You're welcome! And did you manage to solve your problem using this approach?
1

You could have a look at DynamicObject and do something like this:

class Foo<T> : DynamicObject
{
    private T _instance;
    public Foo(T instance)
    {
        _instance = instance;
    }
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        var member = typeof(T).GetProperty(binder.Name);
        if (_instance != null &&
            member.CanWrite &&
            value.GetType() == member.PropertyType)
        {
            member.SetValue(_instance, value, null);
            return true;
        }
        return false;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        var member = typeof(T).GetProperty(binder.Name);
        if (_instance != null &&
            member.CanRead)
        {
            result = member.GetValue(_instance, null);
            return true;
        }
        result = null;
        return false;
    }
}

class Bar
{
    public int SomeProperty { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var bar = new Bar();
        dynamic thing = new Foo<Bar>(bar);
        thing.SomeProperty = 42;
        Console.WriteLine(thing.SomeProperty);
        Console.ReadLine();
    }
}

7 Comments

I can't understand why dynamic typing make sense in the OP's problem. Check the other answer going the same path: the result is just the same as using strong typing.
The difference is that you do not need to implement all the wrapped properties (and methods) but use the TrySet/Get methods. Of course the underlying problem might be solved by using dynamic; I just tried to answer the question about the wrapping.
I guess you mean "the underlying problem mightn't be solved using dynamic" :D I understand your points.
Yes. When a question like this shows up I always doubt the design. But to make this page useful for others, if the question is answerable there should be an answer.
I really believe your solution just hides a bad design decision. Or what's worse: it's the solution for lazies! :D "Since I want to access members as if these were part of the class I make the object dynamic". I want to believe that dynamic objects are for other things, not for avoiding a dot and an identifier when accessing the whole member hahah. But yes, maybe not for this question but any other thing, it's a good demonstration of how powerful are dynamic objects :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.