在 C# 中强制使用方法的特定重载

Gre*_*g B 5 c#-3.0

我有一个重载的通用方法,用于获取类型对象的属性值PageData。属性集合被实现为Dictionary<string, object>. 该方法用于避免检查属性是否有null值以及是否有值的繁琐工作。

一种常见的模式是将 的集合绑定PageData到转发器。然后在中继器中每个PageData都是Container.DataItem类型的object

我针对 PageData 编写了原始扩展方法:

public static T GetPropertyValue<T>(this PageData page, string propertyName);
Run Code Online (Sandbox Code Playgroud)

但是当数据绑定时,你必须将其转换Container.DataItemPageData

<%# ((PageData)Container.DataItem).GetPropertyValue("SomeProperty") %>
Run Code Online (Sandbox Code Playgroud)

我有点痒,想知道我是否无法重载扩展对象的方法,将此方法放在单独的命名空间中(以免污染继承的所有内容object),并且仅在我知道的 aspx/ascx 文件中使用此命名空间我已经数据绑定了PageData. 这样,我就可以避免 aspx/ascx 中的混乱转换,例如

// The new overload
public static T GetPropertyValue<T>(this object page, string propertyName);

// and the new usage
<%# Container.DataItem.GetPropertyValue("SomeProperty") %>
Run Code Online (Sandbox Code Playgroud)

object的版本中GetPropertyValue,我将page参数转换为PageData

public static T GetPropertyValue<T>(this object page, string propertyName)
{
    PageData data = page as PageData;
    if (data != null)
    {
        return data.GetPropertyValue<T>(propertyName);
    }
    else
    {
        return default(T);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将调用转发到我期望的PageData版本GetPropertyValue,但是,我得到了 a,StackOverflowException因为它只是重新调用该object版本。

如何让编译器认识到PageData重载比重载更好匹配object

Jef*_*ado 3

扩展方法语法只是调用对象静态方法的语法糖。就像调用任何其他常规静态方法一样调用它(如果需要,则转换参数)。

IE,

public static T GetPropertyValue<T>(this object page, string propertyName)
{
    PageData data = page as PageData;
    if (data != null)
    {
        //will call the GetPropertyValue<T>(PageData,string) overload
        return GetPropertyValue<T>(data, propertyName);
    }
    else
    {
        return default(T);
    }
}
Run Code Online (Sandbox Code Playgroud)

[编辑]

根据您的评论,我编写了一个测试程序来查看此行为。看起来它确实采用了最本地化的方法。

using System;
using Test.Nested;

namespace Test
{
    namespace Nested
    {
        public static class Helper
        {
            public static void Method(this int num)
            {
                Console.WriteLine("Called method : Test.Nested.Helper.Method(int)");
            }
        }
    }

    static class Helper
    {
        public static void Method(this object obj)
        {
            Console.WriteLine("Called method : Test.Helper.Method(object)");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int x = 0;
            x.Method(); //calls the object overload
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
            Console.WriteLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为了确保嵌套不会影响任何内容,尝试删除对象重载:

using System;
using Test.Nested;

namespace Test
{
    namespace Nested
    {
        public static class Helper
        {
            public static void Method(this int num)
            {
                Console.WriteLine("Called method : Test.Nested.Helper.Method(int)");
            }
        }
    }

    static class Helper
    {
        public static void Method(this string str)
        {
            Console.WriteLine("Called method : Test.Helper.Method(string)");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int x = 0;
            x.Method(); //calls the int overload
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
            Console.WriteLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

果然,int调用了重载。

所以我认为,当使用扩展方法语法时,编译器首先在当前命名空间中查找适当的方法(“最本地的”),然后再查找其他可见的命名空间。