c# - 不必要的接口(interface)转换?

标签 c# interface casting

我正在使用工厂创建 IComparer<User>对象对用户列表进行排序。

我有 2 节课:AscendingDescending , 都实现 IComparer<User> .这是代码:

namespace Test
{
    public class Program
    {
        public static void Main(string[] args)
        {
            List<User> users = new List<User>();
            users.Add(new User("foo", "bar"));
            // ...
            IComparer<User> cmp = ComparerFactory.GetComparer("FirstName", true);
            if (cmp != null)
            {
                users.Sort(cmp);
            }
        }
    }

    public class User
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public User(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }
    }

    public class UserFirstNameComparer
    {
        public class Ascending : IComparer<User>
        {
            public int Compare(User u1, User u2)
            {
                return String.Compare(u1.FirstName, u2.FirstName, true);
            }
        }

        public class Descending : IComparer<User>
        {
            public int Compare(User u1, User u2)
            {
                return new UserFirstNameComparer.Ascending().Compare(u1, u2) * -1;
            }
        }
    }

    public static class ComparerFactory
    {
        public static IComparer<User> GetComparer(string fieldName, bool ascending)
        {
            switch (fieldName)
            {
                case "FirstName":
                    return ascending ?
                        new UserFirstNameComparer.Ascending() : // ERROR IS HERE
                        new UserFirstNameComparer.Descending();
                 //...
            }
            return null;
        }
    }

但我收到一个错误(行:new UserFirstNameComparer.Ascending() :):
Type of conditional expression cannot be determined because there is no implicit conversion between 'Test.UserFirstNameComparer.Ascending' and 'Test.UserFirstNameComparer.Descending'
我不明白这是什么意思,两者都是 IComparer 对象,那有什么问题?
奇怪的是,我可以使用(不必要的?) Actor 来修复错误:
// This works
return ascending ?
    (IComparer<User>) new UserFirstNameComparer.Ascending() :
    new UserFirstNameComparer.Descending();


// This works too
return ascending ?
    new UserFirstNameComparer.Ascending() :
    (IComparer<User>) new UserFirstNameComparer.Descending();

当然,当我在这两种情况下都进行转换时,它会起作用。但我不明白为什么它只适用于一个类型转换,以及为什么没有类型转换时它不起作用。有任何想法吗 ?

(我正在使用 VS 2012,.NET v4.0.30319)

最佳答案

表达方式

cond ? X : Y

只是 需要 (简化)X 的编译时类型可隐式转换为 Y 的编译时类型, 或相反亦然。它不会搜索这两种类型的所有接口(interface)和基类来尝试找到它们的一些“常见”类型。 (即使是这样,它如何处理具有多个通用接口(interface)的情况?)

这就是语言的设计方式。您的方法的返回类型是什么无关紧要,在尝试解析 ?: 时无法考虑。表达。

您已经找到了解决方案,可以转换 X和/或 Y显式地转换为所需的类型。

回答了您的问题后,我还有一个建议,您可以如何在不编写两个类的情况下做到这一点AscendingDescending .您可以创建 IComparer<>像这样:
return ascending
  ? Comparer<User>.Create((u1, u2) => String.Compare(u1.FirstName, u2.FirstName, true))
  : Comparer<User>.Create((u1, u2) => String.Compare(u2.FirstName, u1.FirstName, true))
  ;

所以不需要(可能)你的这两类。

关于c# - 不必要的接口(interface)转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24652983/

相关文章:

ios - 从返回 CGImageRef 的 C 函数将 UnsafeRawPointer 转换为 CGImage 会使 Swift 4 崩溃

c# - 有没有一种干净的方法可以将 C# 'params object[]' 构造函数参数转换为 C++ 构造函数?

c# - 我应该在哪里放置try catch?

java - Android - 使用编译时未知实现的 Java 接口(interface)

generics - 用于处理泛型参数的 JDK 接口(interface)

go - golang中接口(interface)指针和接口(interface)值有什么区别

Java - 从 Object 到 Map.Entry<String,String> 的未经检查的转换

java - 实现 URL.openConnection() 以便可以进行强制转换

c# - 使用 SqlDataSource 保存图像文件

c# - 当您将列表 <> 绑定(bind)到数据网格时 - 如何更改列名?