Search code examples
c#linq

Trying to refactor this to LinQ but getting a invalid cast


So I am wanting to refactor this to LinQ, and not having any luck with it and I am out of search options to guide me in the right direction.

Can someone explain this to me please, as the commented code works and the LinQ well I know I am doing it wrong. Just can't find any information to guide me along.

    public static T Get<T>()
    {
        Type type = typeof(T);

        if (IsRegistered(type))
        {
            //foreach(var service in _services)
            //{
            //    var test = service.InstanceClass;

            //    if(test.GetType().Equals(type))
            //    {
            //        return (T)test;
            //    }
            //}

            return (T) _services.Select(x => x.InstanceClass.GetType() == type);
        }

        return default;
    }

Solution

  • First of all, you want to return T, not bool that's why the final Select is incorrect:

    // Returns `bool`: if "x.InstanceClass" is of type "type"
    Select(x => x.InstanceClass.GetType() == type)
    

    Now let's state the problem:

    1. From _services we want to return first service.InstanceClass which is of type type
    2. If there are no such items, return default

    We can do it like this:

    return _services
      .Select(item => item.InstanceClass) 
      .OfType<T>()
      .FirstOrDefault(item => item.GetType() == type);
    

    A brief explanation on what's going on:

    • We should return some item.InstanceClass from _services so put Select.
    • We are interesting in InstanceClass which can be treated as in instance of type T - that's a purpose of OfType<T>().
    • Finally, we want InstanceClass to be exaclty of type T (and not say, of a derived type) and we put FirstOrDefault with condition.

    The method can look like this:

    public static T Get<T>() {
      // Let's check first for special and edge cases
      if (!IsRegistered(typeof(T)))
        return default;
    
      return _services
       .Select(item => item.InstanceClass) 
       .OfType<T>()
       .FirstOrDefault(item => item.GetType() == typeof(T));
    }