仅在使用 LINQ 时引用需要错误
Reference required error only when using LINQ
我有 3 个 C# projects/assemblies、A、B 和 C。B 引用 A,C 引用 B。
在答:
using System.Collections.Generic;
namespace A
{
public class Dict : Dictionary<string, object> {}
public class Options: Dict {}
}
在 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();
}
}
}
在 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);
}
}
}
这一切编译。
如果我在项目 C 中导入 System.Linq
命名空间并在调用 client.M()
之前添加行 strings.Select(s => s);
(或任何 LINQ 方法),我会收到编译器错误:
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'.
制作 Extensions
class internal
或将其移动到不同的命名空间可以防止错误。
由于 B 应该包装 A 并向 C 隐藏其详细信息,因此将扩展方法设置为 public 是错误的。但是我不明白为什么只有在引入 LINQ 时编译器才会选择它。
是否存在至少一种扩展方法会导致编译器的行为略有不同?
添加任何未解析的方法都会触发此错误。
我不记得是在哪里读到的,但是 C# (VS2013) 编译器在找到匹配的非扩展方法时将停止解析扩展方法。您可以通过在项目 C 中添加以下代码来验证这一点。
public static class Extensions
{
public static void M(this Client c, IDictionary<string, string> d)
{
return;
}
}
它不会导致任何错误!
当一个方法没有用非扩展方法解析时(例如,添加 "abc".Foo()
导致编译器错误),现在 C# 编译器开始扫描扩展方法。当它扫描 B.Extensions.ToDict
时,它不知道 Dict
是什么。但是,程序集 B 的元数据告诉编译器它来自 A.Dict
,然后您会看到错误。
我有 3 个 C# projects/assemblies、A、B 和 C。B 引用 A,C 引用 B。
在答:
using System.Collections.Generic;
namespace A
{
public class Dict : Dictionary<string, object> {}
public class Options: Dict {}
}
在 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();
}
}
}
在 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);
}
}
}
这一切编译。
如果我在项目 C 中导入 System.Linq
命名空间并在调用 client.M()
之前添加行 strings.Select(s => s);
(或任何 LINQ 方法),我会收到编译器错误:
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'.
制作 Extensions
class internal
或将其移动到不同的命名空间可以防止错误。
由于 B 应该包装 A 并向 C 隐藏其详细信息,因此将扩展方法设置为 public 是错误的。但是我不明白为什么只有在引入 LINQ 时编译器才会选择它。
是否存在至少一种扩展方法会导致编译器的行为略有不同?
添加任何未解析的方法都会触发此错误。
我不记得是在哪里读到的,但是 C# (VS2013) 编译器在找到匹配的非扩展方法时将停止解析扩展方法。您可以通过在项目 C 中添加以下代码来验证这一点。
public static class Extensions
{
public static void M(this Client c, IDictionary<string, string> d)
{
return;
}
}
它不会导致任何错误!
当一个方法没有用非扩展方法解析时(例如,添加 "abc".Foo()
导致编译器错误),现在 C# 编译器开始扫描扩展方法。当它扫描 B.Extensions.ToDict
时,它不知道 Dict
是什么。但是,程序集 B 的元数据告诉编译器它来自 A.Dict
,然后您会看到错误。