3

I have these definitions:

public interface IHasId
{
    string Id { get; set; }
}


public class Something : IHasId
{
    public string Id { get; set; }
}


public class Queueable<T>
    where T : IHasId, new()
{
    public T Item { get; set; }
    public int QueueId { get; set; }
}


public class Queue<T>       
    where T : Queueable<T>, IHasId, new()
{
    public void Enqueue(T item)
    {

    }

    public T Dequeue()
    {
        return default(T);
    }
}


public class QueueService
{
    private Queue<Queueable<Something>> queue;
    //private Queue<Queueable<SomethingElse>> somethingElseQueue;
}

When I compile this I'm getting these errors:

**Error**: The type 'test.Queueable<test.Something>' cannot be used as type parameter 'T' in the generic type or method 'test.Queue<T>'. There is no implicit reference conversion from 'test.Queueable<test.Something>' to 'test.IHasId'.

**Error**: The type 'test.Queueable<test.Something>' cannot be used as type parameter 'T' in the generic type or method 'test.Queue<T>'. There is no implicit reference conversion from 'test.Queueable<test.Something>' to 'test.Queueable<test.Queueable<test.Something>>'.

Is this a problem of constraints? I'm thinking on using 2 types for the Queue class, one for the one implementing the IHasId and the other for the Queueable but I'm hoping this is actually simpler to resolve.

Thoughts?

Thanks in advance! R.

3
  • Can you show us the code for the Queue<T> class? Commented Oct 7, 2013 at 22:36
  • Yes, sorry, added now. Commented Oct 7, 2013 at 22:37
  • Queueable<T> is not IHasId just because its T is, but your Queue class expects it to be. Commented Oct 7, 2013 at 22:39

2 Answers 2

3

If I interpret your intention correctly, you want this:

public class Queue<T>       
    where T : IHasId, new()
{
    public void Enqueue(Queueable<T> item)
    {
    }

    public Queueable<T> Dequeue()
    {
        return default(Queueable<T>);
    }
}

Or:

public class Queue<TItem, TQueueable>   
    where TItem : IHasId, new()
    where TQueueable: Queueable<TItem>
{
    public void Enqueue(TQueueable<TItem> item)
    {
    }

    public TQueueable<TItem> Dequeue()
    {
        return default(TQueueable<TItem>);
    }
}

The last one is the post flexible form possible.

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

2 Comments

I think you nailed it. Duh! Thanks! Will try this
I came up with something similar to the second alternative you are suggesting (hence my comment about accepting 2 types in the question) but the 1st suggestion actually makes way more sense as the solution to my problem. Thanks!
1
public class Queue<T>       
    where T : Queueable<T>, IHasId, new()
{ ... }

As you can see, the T inside Queue<T> needs to be both of IHasId and Queueable<T> but the type you put in, Queueable<Something>, isn’t.

You will need to implement both IHasId and Queueable<> on the Queueable<T> type as well. Note that you will probably introduce some more names for the generic type other than T to prevent some recursive requirements or something.

4 Comments

I'm not following. Something implements IHasId, and Queueable<Something> is in compliance with both requirements. What am I missing?
"Something" does, but not the thing that needs too according to your constraint.
In Queue<Queueable<Something>> the T of Queue<T> is Queueable<Something> with the constraints T : Queueable<T>, IHasId. If you would expand this, it would be something like Queueable<Something> : Queueable<Queueable<Something>>, IHasId. I’m not even sure if that would actually make any sense. You should check your constraints.
Yes, you guys are right. The other answer actually is suggesting a better approach to my initial idea; but you made a valid point here too. Thanks!

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.