How to cast argument passed as <T> to some type

JeffinAtl 161 Reputation points
2021-06-14T19:18:32.947+00:00

Here is a code snippet.

public Task ProcessControl<T>(int controltype, T content)
{
    if (controltype == ProcessControl.ResetMachine)
    {
        **var machineoperations = content as IEnumerable<MachineOperation>;**

        Dispatcher.Invoke(() =>
        {
            RefreshResultItem(machineoperations);
        });
    }
    return Task.CompletedTask;
}

Problem is in var machineoperations = content as IEnumerable<MachineOperation>;
The content has correct value.
However machineoperations is always null.
How to case generic type <T> to IEnumerable<SomeType>?

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,843 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Michael Taylor 53,726 Reputation points
    2021-06-14T19:42:51.097+00:00

    Why does this need to be so generic? You should only be using generic methods when the functionality isn't really tied to the type, hence generic. In the common case where you need to be able to use a subset of data then use a generic constraint.

    public Task ProcessControl<T> ( int controltype, T content ) where T: IEnumerable<MachineOperation>
    {
       if (controltype == ProcessControl.ResetMachine)
          Dispatcher.Invoke(() => { RefreshResultItem(content); };
       ...
    }
    

    In this approach ProcessControl will only compile if content is IEnuemrable<MachineOperation>. Or, since your code doesn't work with any type other than the one you expect, just use regular types instead.

    public Task ProcessControl ( int controltype, IEnumerable<MachineOperation> content )
    {
       if (controltype == ProcessControl.ResetMachine)
          Dispatcher.Invoke(() => { RefreshResultItem(content); };
       ...
    }
    

    Note that you can have both generic and non-generic methods so you can leave the generic version but it would have to determine how to proceed in the (probably common) case where the content being passed isn't the exact type you expect.

    Yet another approach, again since you aren't really using generics for what they are designed for, is to just stick with object. There is nothing to be gained by having a generic method like you've defined over object.

    public Task ProcessControl ( int controltype, object content )
    {
       if (controltype == ProcessControl.ResetMachine)
       {
          //What do you do if they don't match
          if (content is IEnumerable<MachineOperation> ops)
             Dispatcher.Invoke(() => { RefreshResultItem(ops); };
       };
       ...
    }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.