C# generi c класс содержит список <T>, но я не могу получить доступ к методам класса <T> - PullRequest
0 голосов
/ 04 мая 2020

У меня есть класс Generi c, DisplayGrid ...

class DisplayGrid<T> where T : class 

..., который имеет List из <T> в качестве свойства.

public List<T> allRows;

... в свойстве DisplayGrid Я хочу перебрать allRows и получить доступ к методу <T> ...

foreach (T r in this.allRows)
{
  if (!(r.isAValidRow))
  {
    blnRowsValid = false;
    break;
  }
}

... однако пытаюсь использовать метод isAValidRow, определенный в <T>, генерирует ошибку компилятора ...

error CS1061: 'T' does not contain a definition for 'isAValidRow' and no extension method 'isAValidRow' accepting a first argument of type 'T' could be found

При чтении старых вопросов кажется, что эта область изменилась за эти годы. Кажется маловероятным, что такое базовое c требование все еще будет невозможно?


EDIT 1 : В первоначальной версии этого вопроса я, возможно, зашел слишком далеко, пытаясь упростить пример кода. Я включил только один класс Row, но я имел в виду, что было несколько классов, которые могли бы использоваться в качестве 'Row' при создании экземпляра класса DisplayGrid.

Теперь я адаптировал приведенные ниже классы таким образом, чтобы в качестве <T> класса DisplayGrid можно было использовать два разных класса.

При выполнении этого я надеюсь обратиться к количество комментариев, в которых правильно указывалось, что нет необходимости использовать Generics или что директива where может быть ограничена единственным классом Row, который я предоставил в примере.

В изменениях к примеру я определил классы RowA и RowB, и я действительно ценю, что, как показано, они функционально идентичны, но это просто для простого примера - при фактическом использовании RowA и RowB будут быть достаточно отличительными, чтобы оправдать, что они не принадлежат к одному и тому же классу.


Полные классы

Все Оба упомянутых выше класса приведены ниже:

class DisplayGrid<T> where T : class  
{
    public List<T> allRows;

    public DisplayGrid()
    {
        this.allRows = new List<T>();
    }

    public bool hasRowMsgs 
    {
        get
        {
            bool blnRowsValid = true;
            foreach (T r in this.allRows)
            {
                if (!(r.isAValidRow))
                {
                    blnRowsValid = false;
                    break;
                }
            }
            return blnRowsValid;
        }
    }
    public bool isAValidTable
    {
        get {
            if (this.hasRowMsgs == false)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}
class RowA
{
    public List<string> rowMsgs;

    public RowA()
    {
        rowMsgs = new List<string>();
    }

    public bool isAValidRow
    {
        get {
            return (this.rowMsgs.Count == 0) ? true : false;
        }
    }
}
class RowB
{
    public List<string> rowMsgs;

    public RowB()
    {
        rowMsgs = new List<string>();
    }

    public bool isAValidRow
    {
        get {
            return (this.rowMsgs.Count == 0) ? true : false;
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 05 мая 2020

После прочтения и понимания значения комментария Ли у меня теперь есть рабочая версия. Ключом к тому, чтобы заставить его работать, было определение интерфейса, IRow и применение его к классам 'Row', RowA и RowB.

Ради будущих читателей здесь приведены классы, которые сейчас работа.

Две точки

  • Я немного изменил код из кода предыдущего примера в свойствах / методах, чтобы сделать их более краткими и устранить несвязанные дефекты;
  • RowA и RowB нереально похожи, это только для того, чтобы проблему можно было проиллюстрировать просто и кратко, ясно, что в реальной реализации они будут менее похожи.

class DisplayGrid<T> where T : IRow 
{
    public List<T> allRows;

    public DisplayGrid()
    {
        this.allRows = new List<T>();
    }

    public bool hasRowMsgs 
    {
        get
        {
            bool blnHasRowMsgs = false;
            foreach (T r in this.allRows)
            {
                if (!(r.isAValidRow))
                {
                    blnHasRowMsgs = true;
                    break;
                }
            }
            return blnHasRowMsgs;
        }
    }
    public bool isAValidTable
    {
        get {
            return (!(this.hasRowMsgs));
        }
    }
}
interface IRow
{
    bool isAValidRow { get; }
}
public class RowA : IRow 
{
    public List<string> rowMsgs;

    public bool isAValidRow {
        get {
            return this.rowMsgs.Count > 0 ? false : true;
        }
    }

    public RowA()
    {
        rowMsgs = new List<string>();
    }
}
public class RowB : IRow 
{
    public List<string> rowMsgs;

    public bool isAValidRow {
        get {
            return this.rowMsgs.Count > 0 ? false : true;
        }
    }

    public RowB()
    {
        rowMsgs = new List<string>();
    }
}
0 голосов
/ 04 мая 2020

Если вы измените первую строку на

class DisplayGrid<T> where T : Row  

, тогда она должна работать.

Объяснение: Метод, который вы пытаетесь использовать, является свойством строки; это не метод класса, поэтому он не распознается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...