gpt4 book ai didi

c# - C# 中的重载解析

转载 作者:行者123 更新时间:2023-11-30 14:15:41 25 4
gpt4 key购买 nike

在特定情况下,我在 C# 中遇到了重载解析问题。在我的 Razor 文件中,我有以下内容:

@foreach (var result in Model.Result)
{
@SearchResult(result)
}

@helper SearchResult(IEntity entity)
{
<p>A normal thing</p>
}

@helper SearchResult(IPhoto photo)
{
<p>A photo! Its title is @photo.Title</p>
}

类结构:

interface IPhoto : IContentItem
interface IContentItem : IEntity

class Photo : ContentItem, IPhoto
class ContentItem : Entity, IContentItem
class Entity, IEntity

实际传递的实例是照片。

SearchResult(IEntity) 在应调用 SearchResult(IPhoto) 时为每个实例调用(或任何 IEntity 导数的实例的最具体重载) .我怎样才能做我想做的事而不必求助于此?

if (result is IXXX) { SearchResultXXX((IXXX)result) }
else if (result is IYYY) { SearchResultYYY((IYYY)result) }
...

最佳答案

由于您的接口(interface)实现,您遇到了这个问题。喜欢ChrisF points out IPhoto 实现了 IContentItem,后者实现了 IEntity。文章C# in Depth: Overloading对重载决策提供了很好的解释,但总而言之:重载在决定调用哪个方法时会忽略任何不正确的方法。来自 overload resolution 上的 Microsoft 规范:

Overload resolution is a compile-time mechanism for selecting the best function member to invoke given an argument list and a set of candidate function members. Overload resolution selects the function member to invoke in the following distinct contexts within C#:

Invocation of a method named in an invocation-expression (Section 7.5.5). Invocation of an instance constructor named in an object-creation-expression (Section 7.5.10.1). Invocation of an indexer accessor through an element-access (Section 7.5.6). Invocation of a predefined or user-defined operator referenced in an expression (Section 7.2.3 and Section 7.2.4). Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way, as described in detail in the sections listed above. For example, the set of candidates for a method invocation does not include methods marked override (Section 7.3), and methods in a base class are not candidates if any method in a derived class is applicable (Section 7.5.5.1).

Once the candidate function members and the argument list have been identified, the selection of the best function member is the same in all cases:

Given the set of applicable candidate function members, the best function member in that set is located. If the set contains only one function member, then that function member is the best function member. Otherwise, the best function member is the one function member that is better than all other function members with respect to the given argument list, provided that each function member is compared to all other function members using the rules in Section 7.4.2.2. If there is not exactly one function member that is better than all other function members, then the function member invocation is ambiguous and a compile-time error occurs. The following sections define the exact meanings of the terms applicable function member and better function member.

为了说明这里是前面提到的 article on overloading 中的一些例子.

任何熟悉重载的人都会意识到,在下面的示例中,static void Foo(string y) 将在 Foo("text") 行被调用时使用。

class Test
{
static void Foo(int x)
{
Console.WriteLine("Foo(int x)");
}

static void Foo(string y)
{
Console.WriteLine("Foo(string y)");
}

static void Main()
{
Foo("text");
}
}

这里有一些更复杂但更好的是与您的问题更相似。编译器将调用 Foo(int x),因为它会寻找更好的函数成员规则,这些规则着眼于(除其他事项外)从每个函数开始所涉及的转换argument 到相应的参数类型(第一种方法为 int,第二种方法为 double)。

class Test
{
static void Foo(int x)
{
Console.WriteLine("Foo(int x)");
}

static void Foo(double y)
{
Console.WriteLine("Foo(double y)");
}

static void Main()
{
Foo(10);
}
}

所有这些都解释了你的情况是 IEntity 是 Photo 的最佳转换,而不考虑存在 IPhoto 过载的事实。这与 Razor @helper 语法无关。为了说明这一点,以下扩展方法存在相同的“问题”。

public static class SearchHelper
{
public static MvcHtmlString SearchResult(this HtmlHelper helper,
IEntity entity)
{
return new MvcHtmlString("A normal thing");
}

public static MvcHtmlString SearchResult(this HtmlHelper helper,
IPhoto photo)
{
return new MvcHtmlString("A photo!");
}
}

最后,我在这里介绍的是更简单的情况——在重载决策中还有其他由泛型、可选参数、继承层次结构等引起的奇怪之处。因此,正如我所看到的那样,您有几个选择:

  1. 使用 .Where lambda 表达式迭代特定类型,将它们传递给适当的助手。
  2. 使用带有 if 语句的单个助手来确定类型并将工作传递给适当的方法。
  3. 想想您的实现策略是否真的是最好的。
  4. 在您的 IEntity 接口(interface)中放置一个渲染方法,并在迭代时调用它(我最不喜欢的选项)

关于c# - C# 中的重载解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9491137/

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