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

本文关键字:表达式 类型 错误 转换 泛型方法 | 更新日期: 2023-09-27 18:19:23

我有两个自定义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);     
}

得到error - Cannot convert expression type '' to return type 'T' in line return tempUc1;

我如何避免它,因为我需要返回这两个类型中的一个?

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

你有一个问题得到你的方法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;

关于你的问题"是否可以用泛型",你应该把泛型看作是在类型无关紧要的情况下可以使用的东西(当函数可以用泛型编写而不需要对可能的类型进行某种特殊情况分析时)。

如果您真的需要为两个UserControls使用相同的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;
}