2017-02-12 22 views
0

Я пытаюсь выяснить, есть ли способ использовать func (или аналогичный метод), примененный к левому объекту. Ex .:C# func <> применяется к объекту слева

member1.MyFunction() 

Вот упрощенный контекст использования. Мы получили ClassA, который содержит список ClassB и метод для суммирования элементов класса B. И classB обладают двумя атрибутами memberX и memberY, которые имеют двойной тип. Функция func должна использоваться для выбора члена ClassB, который мы хотели бы суммировать.

Я получил сообщение об ошибке в строке, где я пишу

theSum += TheList[i].TheFunction(); 

Ошибки:

CS1061 C# не содержит определение и не метод расширения принимающего первый аргумент (вы не можете найти директиву по использованию или ссылку на сборку?)

Кто-нибудь знает обходной путь? Мое исследование не могло привести меня к чему-либо, примененному к левой стороне общей функции.

public class ClassA 
{ 
    public List<ClassB> TheList; 
    public ClassA() 
    { 
     ClassB m1 = new ClassB(1, 2); 
     ClassB m2 = new ClassB(1, 2); 
     ClassB m3 = new ClassB(1, 2); 
     TheList= new List<ClassB>() { m1, m2, m3 }; 
    } 
    private double CalculateSum(Func<double> TheFunction) 
    { 
     double theSum = 0; 
     for (int i = 0; i < TheList.Count(); i++) 
     { 
      theSum += TheList[i].TheFunction(); 
      // I'd like to use the previous line instead of having to write 
      // a function for both of the following. 
      // theSum += TheList[i].GetMember1(); 
      // theSum += TheList[i].GetMember2(); 
     } 
     return theSum; 
    } 
} 
public class ClassB 
{ 
    private double memberX; 
    private double memberY; 
    public ClassB(double x, double y) 
    { 
     memberX = x; 
     memberY = y; 
    } 

    public double GetMember1() { return memberX; } 
    public double GetMember2() { return memberY; } 
} 

ответ

1

Вы могли бы попробовать что-то вроде этого:

private double calculateSum(Func<ClassB, double> aFunction) 
{ 
    double theSum = 0; 
    for (int i = 0; i < aList.Count(); i++) 
    { 
     theSum += aFunction(aList[i]); 
    } 

    return theSum; 
} 

Update

Если вы действительно хотите применить FUNC к объекту слева от неё, то вы могли бы определить метод расширения.

public static class ClassBExtensions 
{ 
    public static double Sum(this ClassB arg, Func<ClassB, double> func) 
    { 
     return func(arg); 
    } 
} 

Затем вызовите его, как этот

Func<ClassB, double> func = null; // define your func here 
for (int i = 0; i < aList.Count(); i++) 
    { 
     theSum += aList[i].Sum(func); 
    } 
return theSum; 
+0

Я пытался избежать этого, но, видя ответы (и результаты поиска), я считаю, что нет другого способа использования Func <> или любых других подобных методов. –

+0

См. Мое обновление, если вы хотите применить func к объекту слева от него. –

3

Ну не с совсем этим синтаксисом, но вы можете просто использовать:

theSum += aFunction(aList[i]); 

Я полагаю, вы могли бы написать метод расширения для этого, но выше более идиоматические.

В самом деле, используя LINQ для начала было бы более идиоматическим - ваш метод calculateSum уже присутствует в LINQ, как Sum, так что вы могли бы назвать:

double sum = aList.Sum(x => x.getMember1()); 

Конечно более идиоматически, вы будете использовать свойство вместо методов:

double sum = aList.Sum(x => Member1); 

Также для идиомы, вы убедитесь, что любые методы, которые вы сделать имеют соглашения об именовании последующих .NET, начиная с заглавной буквы. I strong Советуем вам сразу же последовать правилам именования (даже для демонстрационного кода для демонстрации).

+0

Я чувствую этот ответ должен действительно включить новое определение 'aFunction' для этой первой строки. С 'Func ' это не собирается ничего делать, кроме как дать OP другую ошибку, о которой нужно спросить. – Chris

+0

Я отредактировал свое сообщение, чтобы приблизиться к соглашениям об именах. Спасибо за помощь. –

0

Если я вас правильно понял, вы хотите метод «на» ClassB, который возвращает одно из его значений.(Если ClassB должен иметь такой способ или нет - это может быть просто частью расчета и как таковой на самом деле принадлежность к ClassA - это другой вопрос.)

Если вы можете изменить ClassB, просто добавьте его туда:

public class ClassB 
{ 
    private double memberX; 
    private double memberY; 
    public ClassB(double x, double y) 
    { 
     memberX = x; 
     memberY = y; 
    } 

    public double GetMember1() { return memberX; } 
    public double GetMember2() { return memberY; } 

    public double AFunction() 
    { 
     bool condition = ... 
     return condition ? memberX : memberY; 
    } 
} 

Я использую тройной оператор ?: здесь, чтобы сохранить некоторые пробелы на if/else.

Теперь, если вы можете не изменения ClassB, extension methods (как намекнули в сообщении на CS1061 ошибки) может помочь вам:

public static class ClassBExtensions 
{ 
    public double AFunction(this ClassB b) 
    { 
     bool condition = ... 
     return condition ? b.GetMember1() : b.GetMember2(); 
    } 
} 

Теперь Вы можете просто позвонить .AFunction() по любому экземпляру типа ClassB, как если метод был первоначально объявлен там. Обратите внимание, что методы расширения имеют доступ только к общедоступным полям.

Вы также можете посмотреть в properties, которые позволяют снизить ClassB определения:

public class ClassB 
{ 
    public ClassB(double x, double y) 
    { 
     MemberX = x; 
     MemberY = y; 
    } 

    public double Member1 { get; } 
    public double Member2 { get; } 

    /* 
    public double AFunction() 
    { 
     bool condition = ... 
     return condition ? Member1 : Member2; 
    } 
    */ 
} 
+0

Я определенно собираюсь уменьшить определение класса, как было предложено. Я не знал о существовании методов расширений, это хорошо читается. AsI может изменить класс B, ваше предложение может быть хорошим для меня, но мне все же нужно посмотреть, лучше ли это для моего не упрощенного приложения. –

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