gpt4 book ai didi

.net - 如何在 .NET 中使用 "override"扩展方法?

转载 作者:行者123 更新时间:2023-12-04 12:41:46 28 4
gpt4 key购买 nike

所以我有一个对象层次结构来在 asp.net mvc 中生成 ui 控件并尝试实现流畅的 api。我做了一些虚拟类(class)来专注于当前的问题。
所以这是“错误”的代码库:

public abstract class HtmlElement { /* ... */ }

public abstract class UIElement : HtmlElement { /* ... */ }

public abstract class ButtonBase : UIElement { /* ... */ }

public class LinkButton : ButtonBase { /* ... */ }

public class ActionButton : ButtonBase { /* ... */ }


public static class HtmlElementExtensions
{
public static T Id<T>(this T item, string id) where T : HtmlElement
{
/* set the id */
return item;
}
}

public static class ButtonBaseExtensions
{
public static T Id<T>(this T item, string id) where T : ButtonBase
{
/* set the id and do some button specific stuff*/
return item;
}
}

当我尝试在 LinkBut​​ton 上调用 Id 时,编译器会说存在模棱两可的调用:
LinkButton lb = new LinkButton().Id("asd");

我真的认为编译器在这种情况下会选择最接近的匹配,所以如果我有一个从 HtmlElement 继承的 Script 类而不是调用 HtmlExtensions Id 方法,并且对于 LinkBut​​ton(由于限制),将调用 ButtonBase 方法。
我有一个解决方案,但我不确定是否有更好的解决方案。
我从 ButtonBaseExtensions 中删除了 Id 方法,并按以下方式修改了 HtmlElementExtensions Id 方法:
public static T Id<T>(this T item, string id) where T : HtmlElement
{
if (item is ButtonBase)
{
/* do some button specific stuff*/
}
/* set the id */
return item;
}

这样,ButtonBase 的每个类后代都可以正常工作。
我不太喜欢我的解决方案,因为它将 HtmlElement 逻辑与 ButtonBase 逻辑混合在一起。
任何想法/建议以获得更好的解决方案?
我以为我将它们放在不同的 namespace 中,但只是一秒钟。我应该同时使用两个命名空间,所以不要解决问题。

您认为值得在 msdn 论坛上提及编译器应该注意对泛型扩展方法的限制吗?

与此同时,我进行了更多研究并在 msdn 论坛上创建了一个主题: link
我尝试了一些非通用扩展方法:
  public class BaseClass { /*...*/ }
public class InheritedClass : BaseClass { /*...*/ }

public static class BaseClassExtensions
{
public static void SomeMethod(this BaseClass item, string someParameter)
{
Console.WriteLine(string.Format("BaseClassExtensions.SomeMethod called wtih parameter: {0}", someParameter));
}
}

public static class InheritedClassExtensions
{
public static void SomeMethod(this InheritedClass item, string someParameter)
{
Console.WriteLine(string.Format("InheritedClassExtensions.SomeMethod called wtih parameter: {0}", someParameter));
}
}

如果我实例化这些:
BaseClass bc = new BaseClass();
InheritedClass ic = new InheritedClass();
BaseClass ic_as_bc = new InheritedClass();

bc.SomeMethod("bc");
ic.SomeMethod("ic");
ic_as_bc.SomeMethod("ic_as_bc");

产生了这个输出:
BaseClassExtensions.SomeMethod called wtih parameter: bc
InheritedClassExtensions.SomeMethod called wtih parameter: ic
BaseClassExtensions.SomeMethod called wtih parameter: ic_as_bc

You can vote it for now

谢谢,
彼得

最佳答案

您可以查看有关扩展方法的 MSDN 文档:Extension Methods (C# Programming Guide) .有趣的部分是在编译时绑定(bind)扩展方法下:

... it first looks for a match in the type's instance methods. If no match is found, it will search for any extension methods that are defined for the type, and bind to the first extension method that it finds.



所以这就是你看到这种行为的原因。我实际上可以购买它,想象一下有人可以用一种方法覆盖您的应用程序的工作方式 public static T Id<T>(this T item, string id) where T : object .如果你不会看到任何编译器错误,你会认为一切都是正确的,也许一切都会工作,除了一些极少数情况。会有多困惑?

还有一件关于你的方法的坏事。如果我将使用您的 API 并看到 Button 我有两种方法:一种在 HtmlElementExtensionsButtonBaseExtensions 中的一个什么会阻止我这样做 HtmlElementExtensions.Id(button, "id")而不是 ButtonExtensions.Id(button, "id") ?

在您的情况下,我更喜欢组合方法:
public static T Id<T>(this T item, string id) where T : HtmlElement
{
if (item is ButtonBase)
{
return (T)Id((ButtonBase)item);
}
else if (item is HtmlElement)
{
return (T)Id((HtmlElement)item);
}

throw new NotSupportedException("Type " + item.GetType() + " is not supported by Id extension method");
}

private static ButtonBase Id(ButtonBase item, string id)
{
return item;
}

private static HtmlElement Id(HtmlElement item, string id)
{
return item;
}

关于.net - 如何在 .NET 中使用 "override"扩展方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16140543/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com