I've got 3 C# projects/assemblies, A, B and C. B references A, C references B.
In A:
using System.Collections.Generic;
namespace A
{
public class Dict : Dictionary<string, object> {}
public class Options: Dict {}
}
In B:
using System.Collections.Generic;
using A;
namespace B
{
public class Client
{
public void M(IDictionary<string, string> d)
{
var dict = d.ToDict<Options>();
}
}
public static class Extensions
{
public static T ToDict<T>(this IDictionary<string, string> dictionary)
where T : Dict, new()
{
return new T();
}
}
}
In C:
using System.Collections.Generic;
using B;
namespace C
{
public class Worker
{
public void M()
{
var client = new Client();
var d = new Dictionary<string, string> { { "k", "v" } };
var strings = new [] { "one", "two" }; // never used
client.M(d);
}
}
}
This all compiles.
If I import the System.Linq
namespace in Project C and add the line strings.Select(s => s);
(or any LINQ method) before the call to client.M()
, I get a compiler error:
The type 'A.Dict' is defined in an assembly that is not referenced. You must add a reference to assembly 'A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
Making the Extensions
class internal
or moving it to a different namespace prevents the error.
As B is supposed to be wrapping A and hiding its details from C, it's wrong to let the extension method be public. But I don't understand why this is only picked by the compiler when LINQ is brought in.
Does the presence of at least one extension method cause the compiler to behave slightly differently?
Adding any unresolved method will trigger this error.
I can't remember where I read this, but C# (VS2013) compiler will stop resolving extension method when it find a matching non-extension method. You can verify this by adding following code in project C.
public static class Extensions
{
public static void M(this Client c, IDictionary<string, string> d)
{
return;
}
}
It doesn't cause any error!
When a method is NOT resolved with non-extension method (for example, add "abc".Foo()
to cause a compiler error), now C# compiler starts to scan extension methods. When it scans B.Extensions.ToDict
, it doesn't know what Dict
is. However, assembly B's metadata tell compiler it from A.Dict
, then you see the error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With