无法在泛型方法中转换表达式类型错误

时间:2013-06-20 11:22:29

标签: c# wpf generics

我有两个自定义userControls。当我想将一些属性设置为customUserControl时,我必须做类似的事情:

 private void OnRightMouseDown(object sender, MouseButtonEventArgs e)
 {
     var userControl = sender as UserControl;
     if (userControl != null)
         switch (userControl.Name)
         {
             case "UserControl01":
                 var uc01 = sender as UserControl01;
                 if (uc01 != null)
                 {
                     uc01.ViewModel.IsSelected = true;
                 }
                 break;
             case "UserControl02":
                 var uc02 = sender as UserControl02;
                 if (uc02 != null)
                 {
                     uc02.ViewModel.IsSelected = true;
                 }
                 break;                                                 
          }
     e.Handled = true;
 }

我希望这样做:

private void OnRightMouseDown(object sender, MouseButtonEventArgs e)
 {
     var userControl = sender as UserControl;
     if (userControl != null)
        {
             var tempUc = GetUserControlType(userControl);
             tempUc.ViewModel.IsSelected = true;
        }
     e.Handled = true;
 }

为此,我制作了GetUserControlType方法:

private static T GetUserControlType<T>(T userControl)
    {
        if (userControl != null)
        {
            var uc = userControl as UserControl;
            switch (uc.Name)
            {
                case "UserControl01":
                    var tempUc1 = userControl as UserControl01;
                    return tempUc1;
                case "UserControl02":
                    var tempUc2 = userControl as UserControl02;
                    return tempUc2;
            }
        }
        return default(T);     
}

我收到错误 - Cannot convert expression type '' to return type 'T' in line return tempUc1;

我怎样才能避免它,因为我需要返回这两种类型中的一种?

2 个答案:

答案 0 :(得分:0)

如果你真的需要为两个UserControl使用相同的MouseDown处理程序,你可以这样写:

private void OnRightMouseDown(object sender, MouseButtonEventArgs e)
{
    var uc01 = sender as UserControl01;
    if (uc01 != null)
    {
        uc01.ViewModel.IsSelected = true;
        return;
    }

    var uc02 = sender as UserControl02;
    if (uc02 != null)
    {
        uc02.ViewModel.IsSelected = true;
    }
}

无论如何,更好的解决方案是拥有两个处理程序:

private void UserControl01_RightMouseDown(object sender, MouseButtonEventArgs e)
{
    ((UserControl01)sender).ViewModel.IsSelected = true;
}

private void UserControl02_RightMouseDown(object sender, MouseButtonEventArgs e)
{
    ((UserControl02)sender).ViewModel.IsSelected = true;
}

答案 1 :(得分:0)

将方法正文GetUserControlType置于类型检查中时遇到问题。暂时搁置一下,想象我们实现了GetUserControlType。这样做是将其参数转换为您的一种类型。

返回类型为T,与参数类型相同,因此您的行

var tempUc = GetUserControlType(userControl);

可以改写为

UserControl tempUc = GetUserControlType(userControl);

因为userControl的类型是UserControl。所以基本上,即使你可以得到它来进行类型检查,该方法只会返回其参数不变,并具有相同的类型。您还应该在该行中考虑var的含义 - 它将具有一种特定类型,它不能同时具有UserControl01UserControl02类型。

关于方法本身,行

var tempUc1 = userControl as UserControl01;
return tempUc1;

请勿进行类型检查,因为返回类型T不是静态 UserControl01。它们是否在if语句的特定分支中处于运行时并不重要,它们必须在编译时具有正确的类型。

如评论中所述,您可以使用界面,例如:

interface IControlWithViewModel { public ISelectableViewModel { get; } }
interface ISelectableViewModel { public bool IsSelected { get; set; }

并使用户控件都实现此接口 - 然后编写

var tempUc = (IControlWithViewModel)userControl;
tempUc.ViewModel.IsSelected = true;

除了关于“可以用泛型完成”的问题之外,你应该将泛型视为当类型无关紧要时可以使用的东西(当函数可以写成一般没有对可能的类型进行某种特殊情况分析。)