不必要的ICPCarer?

时间:2011-11-02 15:08:15

标签: c# interface casting

我理解如何将IComparer接口与帮助程序类一起使用,这些辅助程序类提供自定义排序方法。例如,这是一个典型的例子,它非常像我在网上看到的所有例子,包括微软的在线帮助页面:

// This helper class is used to sort an array of people by name, 
// where 'Person' is a class type.
public class PeopleNameComparer : IComparer
{
  // Test the name of each object.
  int IComparer.Compare(object o1, object o2)
  {
     Person p1 = o1 as Person;
     Person p2 = o2 as Person;
     if (p1 != null && p2 != null)
        return string.Compare(p1.Name, p2.Name);
     else
        throw new ArgumentException("Parameter is not a Person!");
  }
}

我也明白如果我们有一个Person(myPeople)类型的数组,我们就可以用这个数组排序:

Array.Sort(myPeople, new PeopleNameComparer());

在这种情况下,我们创建一个新的PeopleNameComparer对象,该对象的类型为IComparer,并将其作为第二个参数传递给Array.Sort()方法。

现在为了使事情变得更整洁,我们可以实现一个属性,为对象用户提供一种更友好的方式来调用自定义排序:

public static IComparer SortByName
{ get { return (IComparer)new PeopleNameComparer(); } }

我不理解这种属性是为什么当这个对象已经是类型时,所有示例都使用(IComparer)强制转换将新创建的辅助类(本例中为PeopleNameComparer)强制转换为IComparer对象IComparer的?我试过没有演员,代码似乎工作正常:

// This property seems to work fine without the cast?
public static IComparer SortByName
{ get { return new PeopleNameComparer(); } }

我可以理解,如果'new'关键字返回一个简单的vanilla System.Object类型,然后必须将其转换为适当的IComparer,但是在这里看不到需要进行转换。 但我遵循微软的例子,我的例子类似于我的Pro C#书中的一个例子。

为什么有必要在这里演员?

4 个答案:

答案 0 :(得分:2)

演员表是多余的。

也许在代码被其他东西重构之前可能是必要的。

通常,在设计发生变化的长系统生命周期中,您会发现代码中存在大量漏洞。

当语言功能发生变化(即C#自动属性)时,您可能还会看到其他冗余结构。

我认为冗余代码会降低可读性,而像Resharper这样的工具会警告您并帮助您删除它们。

答案 1 :(得分:2)

使用显式强制转换更明确。原谅这个真理......但就是这样。它有助于使代码更具可读性。

在某些情况下,如果有多个可能的选项,那么显式强制转换可以帮助运行时消除转换的歧义,但这似乎不会出现在返回类型中。只在表达式中。以下是一个常见示例,您需要在表达式中进行显式强制转换:

public class StringEnumerable : IEnumerable, IEnumerable<String>
{
    IEnumerator<String> IEnumerable<String>.GetEnumerator()
    {
        yield return "TEST";
    }

    public IEnumerator GetEnumerator()
    {
        // without the explicit cast of `this` to the generic interface the 
        // method would call itself infinitely until a StackOverflowException occurs
        return ((IEnumerable<String>)this).GetEnumerator();
    }
}

如果从非泛型接口实现中删除显式转换,则会导致无限循环。

答案 2 :(得分:1)

如果您的问题只是示例将PeopleNameComparer转换为IComparer的原因,那么您完全没有必要。我想这是为了清楚地向初学者证明结果和界面之间存在隐含的关系。

答案 3 :(得分:1)

我不知道“所有”示例,但实际上代码的两个变体应该完全相同。也许他们只是认为明确的演员更具可读性。