Click here to Skip to main content
16,017,707 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
I am not strong on generic class. Say we have a class.
C#
class Appointment
    {
        public Guid UniqueId { get; set; }
    }

And an extensiton class:
C#
public static class ExtendReceive<T> where T:Appointment
    {
        public static void TryReceive<T>(this BufferBlock<T> bufferBlock, int count)
        {
            try
            {
                for (var i = 0; i < count; i++)
                {
                    T item;
                    if (bufferBlock.TryReceive(out item))
                    {
                        Call d = new Call();
                        d.RunScript<T>((T)item);
                    }
                    else
                    {
                        break;
                    }
                }
            }

And finally
C#
class Call
    {
       
        internal void RunScript<T>(T t)
        {
            var x = t.UniqueId;
        }

However this line is wrong:
C#
var x = t.UniqueId; //error

Also we call this extension method also got error:
C#
public static BufferBlock<Appointment> m_Queue = new BufferBlock<Appointment>();
m_Queue.TryReceive(4); // error as well

The best overload method match ...has some invalid arguments.

Thanks for advice.
Posted
Comments
Sergey Alexandrovich Kryukov 8-Oct-14 22:58pm    
Where is the declaration of BufferBlock? And BufferBlock.TryReceive?
—SA
BillWoodruff 9-Oct-14 6:06am    
For a question like this about "best practices" it's a good thing to state what you are trying to achieve in your question. What is your goal here ? Why did you choose to write an Extension Method that then creates a new Class every time it needs to execute 'RunScript ?

You started correctly, and then made a mess. How a compiler can know that x has the member UniqueId?

You need to do it as in the generic class ExtendReceive. In this class, the compiler knows that the parameter is Appointment (this exact type or derived from this class), due to the constraint where T: Appointment. This is the whole idea behind those constraints.

In case of second error, I the declaration of System.Threading.Tasks.Dataflow.BufferBlock.TryReceive (thanks for clarification) shows this signature (http://msdn.microsoft.com/en-us/library/hh194808%28v=vs.110%29.aspx[^]):
C#
public static bool TryReceive<TOutput>(
	this IReceivableSourceBlock<TOutput> source,
	out TOutput item
)

I have no idea why did you decide that there is a method with the same name expecting an integer argument. Moreover, this method is static, you cannot possibly call it on m_Queue, the call syntax would be BufferBlock.TryReceive(/* ... */). Here, you have a problem with programming basics, not even specifically related to .NET generics.

—SA
 
Share this answer
 
v5
Comments
[no name] 9-Oct-14 8:46am    
@SA,
BufferBlock is .net 4.5 Tasks Parallel Library. see http://msdn.microsoft.com/en-us/library/hh160414(v=vs.110).aspx

public sealed class BufferBlock<t> : IPropagatorBlock<t, t="">, ITargetBlock<t>, IReceivableSourceBlock<t>, ISourceBlock<t>, IDataflowBlock
Sergey Alexandrovich Kryukov 9-Oct-14 10:50am    
Thank you for clarification, but I already answered, so one problem was apparent even without seeing the declaration. Additional issue is that the method is generic. In all cases, you just tried to call a method which simply does not exist, hence the second error.
—SA
Maciej Los 9-Oct-14 10:49am    
+5!
Sergey Alexandrovich Kryukov 9-Oct-14 10:53am    
Thank you, Maciej.
—SA
You declared a static class with Generic type. Static classes cannot be instantiated and you will end up using the class name which will diminish the purpose of declaring an extension method.

Instead of declaring generic on static class put the constraint on the extension method itself.
C#
public static class ExtendReceive 
    {
        public static void TryReceive<t>(this BufferBlock<t> bufferBlock, int count)                 where T:Appointment

        {
            try
            {
                for (var i = 0; i < count; i++)
                {
                    T item;
                    if (bufferBlock.TryReceive(out item))
                    {
                        Call d = new Call();
                        d.RunScript<t>((T)item);
                    }
                    else
                    {
                        break;
                    }
                }
            }
</t></t></t>


In case of class Call, you need to decide whether you need the generic type reference throughout the call or only for the method RunScript and accordingly add constraint
C#
class Call
    {
       
        internal void RunScript<t>(T t) where T:Appointment
        {
            var x = t.UniqueId;
        }
</t>
 
Share this answer
 
Comments
BillWoodruff 9-Oct-14 6:02am    
+5 given the lack of information from the OP about what their goals are, and why they chose to wrote the (rather odd) code they wrote, I think this is a "best possible" answer.
Maciej Los 9-Oct-14 10:47am    
Good job!
+5!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900