'cannot convert from class to 'T' [closed]

I have the following code:

await ProcessBuffer<ChannelItem>(item);
await ProcessBuffer<SiteItem>(item).Wait();
await ProcessBuffer<SiteMailItem>(item).Wait(); 

private async Task ProcessBuffer<T>(ServiceBusMigratedItemMessage item)
{
    System.Collections.Concurrent.ConcurrentQueue<T> buffer = null;
    buffer = new System.Collections.Concurrent.ConcurrentQueue<T>();
     switch (type.ToString())
        {               
            case nameof(SiteItem):
                buffer.Enqueue(ConvertSiteMessage(item));
                break;
            case nameof(ChannelItem):
                ChannelItem truc = ConvertChannelMessage(item);
                buffer.Enqueue(truc);
                break;
            case nameof(SiteMailItem):
                buffer.Enqueue(ConvertSiteMailMessage(item));
                break;
        }   
    buffer.Enqueue(something);

It raises this error in line buffer.Enqueue Error CS1503 Argument 1: cannot convert from 'Models.Sites.ChannelItem' to 'T'

or cannot convert from 'Models.Sites.SiteItem' to 'T'

etc...

public class ChannelItem : CacheItem
{
}

 private ChannelItem   ConvertChannelMessage(ServiceBusMigratedItemMessage migratedItem)
{
}
 private SiteMailItem  ConvertSiteMailMessage(ServiceBusMigratedItemMessage migratedItem)
{
}

I don't know how to cast and enqueue the channelItem?



Solution 1:[1]

await ProcessBuffer<ChannelItem>(item);
private async Task ProcessBuffer<T>(Someclass item)
{
    System.Collections.Concurrent.ConcurrentQueue<T> buffer = null;
    buffer = new System.Collections.Concurrent.ConcurrentQueue<T>();
    ChannelItem something= new ChannelItem();
    buffer.Enqueue(something);

The above is your original code.

Your code has:

ConcurrentQueue<T> buffer

so only "T's" can be put in the ConcurrentQueue

So you need either:

(1)

Change your ConcurrentQueue generic-type:

ConcurrentQueue<ChannelItem> buffer

or (2) you need to put only T items in your ConcurrentQueue

maybe you mean to code the below?

(note the change to "T item" in the method signature?/

await ProcessBuffer<ChannelItem>(item);
private async Task ProcessBuffer<T>(T item)
{
    System.Collections.Concurrent.ConcurrentQueue<T> buffer = null;
    buffer = new System.Collections.Concurrent.ConcurrentQueue<T>();
    buffer.Enqueue(item);

or (3) many you mean (and need) to "constrain" the Generic.

await ProcessBuffer<ChannelItem>(item);
private async Task ProcessBuffer<T>(T item) where T : CacheItem
{
    System.Collections.Concurrent.ConcurrentQueue<T> buffer = null;
    buffer = new System.Collections.Concurrent.ConcurrentQueue<T>();

    buffer.Enqueue(item);

See : https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters

In the above microsoft URL, look for this code sample:

public static void OpEqualsTest<T>(T s, T t) where T : class
{
    System.Console.WriteLine(s == t);
}

(You've now edited your question)

or 4

you may need a "marker" interface.

public interface IMyMarker()
{
}


public class ChannelItem : IMyMarker
{
}


public class SiteItem : IMyMarker
{
}


public class SiteMailItem : IMyMarker
{
}

and now constrain T to IMyMarker

private async Task ProcessBuffer<T>(T item) where T : IMyMarker
{
    System.Collections.Concurrent.ConcurrentQueue<T> buffer = null;
    buffer = new System.Collections.Concurrent.ConcurrentQueue<T>();

    buffer.Enqueue(item);

Here's the bottom line.

If you define a

ConcurrentQueue<T>

you can put ~~only "T's" on it.

you can "constrain" the T's some, but you can never break the rule that "you can put ~only T's" on the

  ConcurrentQueue<T>

Solution 2:[2]

System.Collections.Concurrent.ConcurrentQueue<ChannelItem> buffer = null;
    buffer = new System.Collections.Concurrent.ConcurrentQueue<ChannelItem>();

Just change the T to ChannelItem

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 DamnScandalous