Используйте foreach для класса, а не для коллекции класса

Итак, у меня есть этот класс со строками, поплавками, DateTimes и таблицами данных.

public class Data : IEnumerator
{

    string m_PowerSwitch = "Not Tested",
        m_SerialNumber = "Not Tested",
        m_Reset = "Not Tested",
        m_WashPump = "Not Tested",

        m_PortB = "Not Tested",
        m_PortC = "Not Tested",
        m_PortD = "Not Tested",
        m_CurlyTube = "Not Tested",
        m_BypassTube = "Not Tested";

    float m_EC53115VMeasured = 0.0F,
        m_EC53165VMeasured = 0.0F,
        m_EC531624VMeasured = 0.0F,

        m_SolventLineBVolumeMeasured = 0.0F,
        m_SolventLineCVolumeMeasured = 0.0F,
        m_SolventLineDVolumeMeasured = 0.0F,
        m_CurlyTubeVolumeMeasured = 0.0F,
        m_BypassTubeVolumeMeasured = 0.0F;
} 

Я хочу использовать оператор foreach, например

        foreach (ASM001.ASM asm in P00001.Global.ListofAvailableASMs)
        {  
            if (asm.ASMData.EndTime == null)
                asm.ASMData.EndTime = endTime;

            foreach (object data in asm.ASMData)
            {
                if (data == "Not Tested")
                {
                    asm.ASMData.Result = "FAILED";
                }
                continue;
            }

но мне не удалось найти помощь в поиске по отдельным полям класса, только в списке типа класса.

Я получаю сообщение об ошибке: оператор foreach не может работать с переменными типа «ASM001.Data», поскольку «ASM001.Data» не содержит общедоступного определения для «GetEnumerator».

Мне было интересно, возможно ли это или мне придется жестко кодировать каждое строковое поле по имени и возвращать true или false.

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


person Josh Davis    schedule 13.04.2015    source источник
comment
разве не должно быть IEnumerable вместо IEnumerator?   -  person DLeh    schedule 13.04.2015
comment
@Предоставьте каждой строке общедоступное свойство, исключающее m_   -  person Josh Davis    schedule 13.04.2015
comment
@DLeh это вполне может быть, но это все еще не решает мою проблему   -  person Josh Davis    schedule 13.04.2015
comment
@JoshDavis хорошо решает ошибку does not contain a public definition for 'GetEnumerator'   -  person DLeh    schedule 13.04.2015
comment
Вы не можете перечислять такие поля класса. Вам нужно будет использовать отражение и вытащить список полей.   -  person James Wilkins    schedule 13.04.2015
comment
@JamesWilkins это неправда. foreach может использоваться во всем, что реализует IEnumerable<T>, делать это для типа, который не представляет какую-либо последовательность элементов, не имеет большого смысла, но это, безусловно, возможно. Для OP вы реализуете неправильный интерфейс. Часть Enumator - это лишь малая часть того, что требуется, чтобы сделать тип "доступным для достижимости" (перечисляемым). Это может помочь stackoverflow.com/questions/11296810/   -  person evanmcdonnal    schedule 13.04.2015
comment
Это не то, что я имел ввиду. Вы не можете просто использовать IEnumerator для класса, чтобы прочитать его свойства, или IEnumerable‹›. Однако вы МОЖЕТЕ реализовать методы интерфейса для чтения полей класса, если вы запрограммируете его для этого (но следует ли это делать — это отдельная тема).   -  person James Wilkins    schedule 13.04.2015


Ответы (3)


Используйте Reflection (код перефразирован, это не будет построено)

Data data = ...
Type type = data.GetType();
FieldInfo[] fields = type.GetFields(...);
foreach(FieldInfo field in fields) {

    Console.WriteLine("{0} = {1}", field.Name, field.GetValue( data ) );
}
person Dai    schedule 13.04.2015
comment
Должен был указать, что каждое поле имеет общедоступное свойство, на что я смотрю, но это было простое исправление, и я смог понять это из того, что вы сказали. - person Josh Davis; 13.04.2015

Из MSDN (следующий пример должен собраться и запуститься):

В следующем примере извлекаются поля MyClass и отображаются значения полей.

using System;
using System.Reflection;

public class MyClass
{
    public string myFieldA;
    public string myFieldB; 
    public MyClass()
    {
        myFieldA = "A public field";
        myFieldB = "Another public field";
    }
}

public class FieldInfo_GetValue
{
    public static void Main()
    {
        MyClass myInstance = new MyClass();
        // Get the type of MyClass.
        Type myType = typeof(MyClass);
        try
        {
            // Get the FieldInfo of MyClass.
            FieldInfo[] myFields = myType.GetFields(BindingFlags.Public 
                | BindingFlags.Instance);
            // Display the values of the fields.
            Console.WriteLine("\nDisplaying the values of the fields of {0}.\n",
                myType);
            for(int i = 0; i < myFields.Length; i++)
            {
                Console.WriteLine("The value of {0} is: {1}",
                    myFields[i].Name, myFields[i].GetValue(myInstance));
            }
        }  
        catch(Exception e)
        {
            Console.WriteLine("Exception : {0}", e.Message);
        }
    }
}
person Pseudonym    schedule 13.04.2015
comment
Разве это не потянет только общественные поля? - person James Wilkins; 13.04.2015
comment
Хм, я не сразу в этом уверен. Я буду копаться в этом еще немного - person Pseudonym; 13.04.2015
comment
Из статьи, которую я связал: ограничения доступа игнорируются для полностью доверенного кода. То есть к закрытым конструкторам, методам, полям и свойствам можно обращаться и вызывать их посредством отражения всякий раз, когда код полностью доверен. - person Pseudonym; 13.04.2015

Возможная версия LINQ:

Data data = ...
FieldInfo[] fields = (from f in data.GetType().GetFields(BindingFlags.Instance|BindingFlags.NonPublic) where f.Name.StartsWith("m_") select f).ToArray();
person James Wilkins    schedule 13.04.2015