简体   繁体   中英

Cannot convert expression type error in generic method

I have two custom userControls. And when I want to set some property to customUserControl, I have to do something like that:

 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;
 }

and I want to do it this way:

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;
 }

For that purpose I made GetUserControlType method:

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);     
}

And I get error - Cannot convert expression type '' to return type 'T' in line return tempUc1;

How can I avoid it, because I need to return one of this two types?

If you really need to have the same MouseDown handler for both UserControls, you may write it like this:

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;
    }
}

Anyway, the better solution would be to have two handlers:

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;
}

You have a problem getting the body of your method GetUserControlType to typecheck. Leaving that aside for a moment, imagine that we had an implementation of GetUserControlType . What this does is return its argument cast to one of your types.

The return type is T , the same as the argument type, so your line

var tempUc = GetUserControlType(userControl);

could be rewritten as

UserControl tempUc = GetUserControlType(userControl);

since the type of userControl is UserControl . So basically, even if you could get it to typecheck, the method would just return its argument unchanged, and have the same type. You should also think what you mean by var in that line - it will have one particular type, it cannot have both type UserControl01 and UserControl02 .

As to the method itself, the lines

var tempUc1 = userControl as UserControl01;
return tempUc1;

don't typecheck because the return type T is not statically UserControl01 . It doesn't matter whether they would be at runtime in that particular branch of the if statement, they have to have the correct type at compile time.

As noted in a comment, you can use an interface, eg:

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

and make the user controls both implement this interface - then instead you write

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

Further to your question as to "can it be done with generics", you should think of generics as something which can be used when the type doesn't matter (when the function can be written generically without some kind of special-case analysis on the possible types).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM