Linq puzzle ... equivalent syntax ... not equivalent results!

There is exactly one type in the code that implements IResourceConverter. This is what the following two linq expressions are looking for. The first does not find. The latter does. However, both are equivalent syntaxes (or at least should be!).

Linq Statement 1:

List<Type> toInstantiate = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(assembly => assembly.GetTypes())
    .Where(type => typeof(IResourceConverter).IsAssignableFrom(type) 
        && type != typeof(IResourceConverter))
    .ToList();

This returns 0 results.

Linq Statement 2:

I left linq intact, with the exception of the where clause, which I broke out, and made an equivalent with the foreach loop

List<Type> toInstantiate = new List<Type>();            
List<Type> allTypes = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(assembly => assembly.GetTypes())
    .ToList();

foreach (Type t in allTypes)
{
    if (typeof(IResourceConverter).IsAssignableFrom(t) 
        && t != typeof(IResourceConverter))
    toInstantiate.Add(t);
}

In this case, toInstantiate has 1 result ... exactly what I expected.

Any explanation for this weird behavior?

+3
source share
4 answers

a.txt b.txt .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Reflection;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = Foo().OrderBy(t => t.FullName).Select(t => t.FullName);
            var y = Bar().OrderBy(t => t.FullName).Select(t => t.FullName);

            File.WriteAllLines("a.txt", x.ToArray());
            File.WriteAllLines("b.txt", y.ToArray());
            Console.ReadKey();
        }

        private static List<Assembly> Foo()
        {
            List<Type> toInstantiate = AppDomain.CurrentDomain
                .GetAssemblies().SelectMany(assembly => assembly.GetTypes())
                .ToList();

            return toInstantiate.Select(t => t.Assembly).Distinct().ToList();
        }

        private static List<Assembly> Bar()
        {
            List<Type> toInstantiate = new List<Type>();
            List<Type> allTypes = AppDomain.CurrentDomain
                .GetAssemblies().SelectMany(assembly => assembly.GetTypes())
                .ToList();

            foreach (Type t in allTypes)
            {
                toInstantiate.Add(t);
            }

            return toInstantiate.Select(t => t.Assembly).Distinct().ToList();
        }
    }
}

, . , Bar , linq.

, , Foo , , .. .

, , , :

    Foo, Foo, Bar
    Foo, Bar, Foo
    Bar, Bar, Foo
    Bar, Foo, Bar

.

, - , .

+2

, , .

List<Type> allTypes = AppDomain.CurrentDomain
    .GetAssemblies().SelectMany(assembly => assembly.GetTypes())
    .ToList();

List<Type> toInstantiate = allTypes
    .Where(type => typeof(IList).IsAssignableFrom(type) && type != typeof(IList))
    .ToList();

foreach, - . , . .

+2

LINQ, ; , Hibernate ( Java ORM):

Hibernate Collection . , Hibernate - -, Parent . :

class Test {
 Collection<Parent> getEntities() //lazy
}

class Parent extends Child {
}

class Child {
}

getEntities(), . getEntities , Parent. , : "myEntity instanceof Child" , - , .

, LINQ - , . , , "type" where - - - Type, , isAssignable() , - IResourceConverter?

0
source

Make sure that the expression below evaluates to true (i.e., deduces it from the LINQ statement and evaluates it directly against the type itself):

bool doesImplIface = typeof(IResourceConverter).IsAssignableFrom(type) && type != typeof(IResourceConverter);

The only reason the Where clause filters out the result is because the expression does not evaluate to true. The execution of the above line of code should clearly indicate whether the expression you are trying to execute does as you think or not. If not, tweak it until you get the appropriate behavior, and put the new expression in the LINQ statement.

0
source

Source: https://habr.com/ru/post/1716926/


All Articles