2013-09-30 3 views
0

Я зову общий метод с двумя различными классами, как показано ниже:свойство класса не доступны универсальный метод C#

FillDataPointsInOrder<Metrics>(dataPoints.Where(O => O.SortOrder != null).OrderBy(O => O.SortOrder)); 
FillDataPointsInOrder<Metric>(angieStatsCmp.GetDataColumns()); 


private void FillDataPointsInOrder<T>(IEnumerable<T> dataPoints) 
{ 
    foreach (T dpoint in dataPoints) 
    { 
     if (!dpoint.IsPhone) 
      FillDrp(this.EmailDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName); 

     if (dpoint.IsPhone && this.IsPhoneShop) 
      FillDrp(this.PhoneDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName); 
    } 
} 

в «FillDataPointsInOrder» метод я получаю ошибку компиляции:

'T' does not contain a definition for 'IsPhone' and no extension method 'IsPhone' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?) 

Те же ошибки для свойств Name, MetricId и VName. Не знаете, почему T не имеет доступа к свойствам показателей и метрик. Если я удалю код из универсального метода и напишу его непосредственно в foreach поверх dataPoints, он работает нормально.

Может кто-нибудь сообщить, что здесь не так?

ответ

1

FillDataPointsInOrder только знает, что он будет называться с помощью T. T действительно может быть строкой, int или чем угодно.

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

Но в этом случае похоже, что ваш метод даже не должен быть общим. Если оба Metric и Metrics доля базового класса или интерфейс, который обладает свойствами, вам необходимо:

interface IMetric { 
    bool IsPhone {get; } 
} 

вы могли бы просто:

private void FillDataPointsInOrder(IEnumerable<IMetric> dataPoints) 

Обратите внимание, что IEnumerable ковариантен, так что если Metric является IMetric, IENumerable<Metric> is IEnumerable<IMetric>

+0

Хорошая точка. В примере, приведенном в вопросе, нет очевидной потребности в универсальном методе, в первую очередь, если существует соответствующий интерфейс или базовый класс. – Xiaofu

1

Вам нужно как минимум рассказать компилятору о Т, если вы хотите это сделать. У вас есть интерфейс с такими членами, как IsPhone, Name, MetricId и т. Д., Которые реализуются вашими классами?

Если так что вы можете добавить «где» ограничение на ваше определение класса:

public class Something<T> where T : ISomethingElse 

... где ISomethingElse интерфейс, который реализует IsPhone.

Смежные вопросы