我有:
为什么我需要在LibaryB中使用using语句才能让他们的扩展方法在主类中工作?这是因为它是库B,它定义了将被扩展的类。
编辑 - 代码
除外 // *** PROGRAM ***
using TopologyDAL;
using Topology; // *** THIS WAS NEEDED TO GET EXTN METHODS APPEARING ***
class Program
{
static void Main(string[] args)
{
var context = new Model1Container();
Node myNode; // ** trying to get myNode mixin methods to appear seems to need using line to point to Library B ***
}
}
// ** LIBRARY A
namespace TopologyDAL
{
public partial class Node
{
// Auto generated from EF
}
public partial class Node : INode<int> // to add extension methods from Library B
{
public int Key
}
}
// ** LIBRARY B
namespace ToplogyLibrary
{
public static class NodeExtns
{
public static void FromNodeMixin<T>(this INode<T> node) {
// XXXX
}
}
public interface INode<T>
{
// Properties
T Key { get; }
// Methods
}
}
答案 0 :(得分:3)
扩展方法仅在您导入定义的命名空间时才可用。
否则,编译器需要针对每个引用的库中的每个扩展方法进行解析,这会减慢编译时间。
此外,如果不同的命名空间包含具有相同签名的扩展方法,则无法使用扩展方法。
总之,扩展方法本身就是功能,需要导入其命名空间;它们不会自动导入它们扩展的类的命名空间。
答案 1 :(得分:2)
这是扩展方法的一个令人遗憾的可发现性问题。为了使它们可用,您需要为包含具有扩展的静态类的命名空间添加using
语句。查看此blog有关扩展方法的信息。
以下是关于扩展方法的some background:
那么编译器如何知道哪个 扩展方法绑定?编译器 寻找扩展方法 调用时最内层的命名空间 为扩展方法,然后在 由...导入的所有命名空间 “使用”条款。这个过程是 然后向外移动直到我们到达 最顶层的命名空间。
因为扩展方法可以 导入到当前上下文中 “使用”子句并绑定到任何 可分配的对象(见 兑换部分详情) 实例参数,各种各样的 有趣的可能性开放 扩展a实现的方法 类型。这可以简单地完成 导入扩展库 方法并使用这些方法,如果 他们被宣布为你的类型 不拥有。这意味着
根据您导入的库,可以使代码做不同的操作 的东西。
- 醇>
客户端获得了一种扩展他不拥有的类型的有趣方式。
我的理解是使用扩展方法就像使用任何其他类型一样,除了你不能限定它们(这在语法上是不可能的),因此需要using
语句。由于您可以在不同的名称空间中的不同类中定义它们中的多个,因此编译器需要一种方法来解决歧义。
我设想将来在Visual Studio中添加一个功能,以便在键入方法名称时导入正确的命名空间,其方式类似于类和接口名称。
考虑这种情况:
namespace FruityNamespace {
public static class FruityExtensions {
public static string ToFunString(this int value) {return value + " bananas"; }
}
}
namespace VegetablNamespace {
public static class VegetablyExtensions {
public static string ToFunString(this int value) {return value + " carrots"; }
}
}
//In some other source file
static void Main(/**/) {
int things = 3;
3.ToFunString(); //error CS1061: 'System.Int' does not contain a definition for 'ToFunString' and no extension method 'ToFunString' accepting a first argument of type 'System.Int' could be found (are you missing a using directive or an assembly reference?)
}
要使用任何这些扩展方法,您需要导入正确的命名空间:
using FruityNamespace;
//OR
using VegetablyNamespace;
您可能会问到导入两个命名空间时会发生什么。你得到一个编译器错误:
error CS0121: The call is ambiguous between the following methods or properties: 'VegetablNamespace.VegetablyExtensions.ToFunString(int)' and 'FruityNamespace.FruityExtensions.ToFunString(int)'