Дженерики, похоже, не совпадают по классу и методу

#c# #generics

#c# #дженерики

Вопрос:

Я задавал этот вопрос раньше, но он был отложен, потому что проблема была «простой» проблемой преобразования. Для меня это не так. Я впервые пытаюсь работать с дженериками.

У меня есть Class похожий код здесь без каких-либо ошибок:

 internal class GridBox<T> : BoxBase // where T : new()
{
    public GridBox(Grid grid, GridBoxView view, MessageBoxIcon icon, string caption, ObservableCollection<T> dataSource, MessageBoxButton button)
        : base(grid, icon, caption, button)
    {
        View = view;
        DataSource = dataSource;
    }

    public GridBoxView View { get; set; }
    public ObservableCollection<T> DataSource { get; set; }
}
 

Затем я использую это Class для передачи большого количества данных между разными Classes , начиная с кода ниже:

 public static T Show<T>(DependencyObject sender, MessageBoxIcon icon, string caption, ObservableCollection<T> dataSource, MessageBoxButton button) where T : IComparable<T>, new()
{
    Window window = Window.GetWindow(sender);
    Grid grid = Extensions.FindChild<Grid>(window);
    GridBoxView gridBox = new GridBoxView();

    return gridBox.Show<T>(new GridBox<T>(grid, gridBox, icon, caption, dataSource, button));
}
 

Этот код может быть скомпилирован без каких-либо ошибок. Прав ли я, если скажу, что where T : IComparable<T> это необходимо для использования T внутри Method , а , new() для его использования требуется дополнительное new GridBox<T> ? Опять же, впервые экспериментирую с дженериками.

Приведенный выше код, который вызывает Show<T> , приведен ниже:

 internal class GridBoxViewModel<T> : BoxBaseViewModel // where T : new()
{
    public T Show<T>(GridBox<T> gridBox)
    {
        // Set content item
        DataSource = gridBox.DataSource;

        // Set visual items and block the excecution code 
        AddView(gridBox.Grid, gridBox.View, gridBox.Icon, gridBox.Caption, gridBox.Button);

        // Return value
        return SelectedItem;
    }

    public ObservableCollection<T> DataSource { get; set; }
    public T SelectedItem { get; set; }
}
 

Здесь начинаются проблемы. DataSource = gridBox.DataSource выдает ошибку, которую он не может преобразовать System.Collections.ObjectModel.ObservableCollection<T> System.Collections.ObjectModel.ObservableCollection<T> , которая представляется мне такой же. Оба ссылаются на одно и то же Class Library [C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5System.dll] .

Вторая проблема связана с return SelectedItem; . Ошибка здесь практически такая же, но немного отличается. Он не может быть преобразован 'T' в 'T [ControlsViewModelsGridBoxViewModel.cs(6)]' .

Очевидная причина для меня в том, что T at internal class GridBoxViewModel<T> : BoxBaseViewModel не совпадает T с at public T Show<T>(GridBox<T> gridBox) . Действительно ли это причина, и если да, то как мне справиться с этой проблемой и исправить ее?

Комментарии:

1. Как вы ожидаете, что компилятор сделает вывод, что T from GridBoxViewModel и T from GridBox имеют один и тот же тип или имеют неявное преобразование между ними?

2. where T: new() означает, что только типы с конструкторами без параметров являются допустимыми аргументами типа (что позволяет вызывать new T(); в классе / методе), и where T: IComparable<T> означает IComparable<T> , что в качестве аргументов типа могут использоваться только типы, реализующие интерфейс (что позволяет вызывать CompareTo T в классе / методе). Похоже, вы не используете ни один из них в показанном вами коде, поэтому я не уверен, что они вам нужны.

Ответ №1:

Удалите общий параметр из Show :

 public T Show(GridBox<T> gridBox)
 

параметр T типа отличается от параметра, объявленного в классе, поэтому вы получаете ошибку компилятора.

Комментарии:

1. Хех, я думаю, довольно очевидно. Это фактически исправило это, tnx. Теперь я могу начать тестирование своего кода, если он действительно работает.