我正在使用工厂创建IComparer<User>
个对象来对用户列表进行排序。
我有两个课程:Ascending
和Descending
,都是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对象,那么问题是什么? 奇怪的是,我可以用(不必要的?)演员来修复错误:
// 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)
答案 0 :(得分:4)
new UserFirstNameComparer.Ascending()
返回Ascending
的实例。
new UserFirstNameComparer.Descending()
会返回Descending
的实例。
即使两者都实现IComparer
,这些实例的类型也不同。当您将其中一个投射到IComparer
时,生成的对象的类型为IComparer
。现在可以进行隐式转换,因为一个是接口,另一个是实现它的类。
引用文档,了解条件表达式
condition ?: first_expression : second_expression
first_expression
和second_expression
的类型必须相同,或者从一种类型到另一种类型必须存在隐式转换。
答案 1 :(得分:4)
表达式
cond ? X : Y
只需需要(简化),编译时类型X
可隐式转换为编译时类型Y
,反之亦然。它不会搜索这两种类型的所有接口和基类来尝试找到它们的一些“常见”类型。 (即使它确实如此,它将如何处理具有多个通用接口的情况?)
这就是语言的设计方式。与您的方法的返回类型无关,在尝试解析?:
表达式时无法将其考虑在内。
您已找到解决方案,明确地将X
和/或Y
投射到所需类型。
在回答了您的问题之后,我也建议您如何在不编写Ascending
和Descending
两个课程的情况下完成此操作。您可以像这样创建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))
;
所以不需要(可能)这两类你的。