Как мне получить значение внутри класса, хранящегося в массиве?

#c# #arrays #class #unity3d

#c# #массивы #класс #unity3d

Вопрос:

Я создаю скрипт на C # в Unity. Я намереваюсь создать класс Scenario , создать классы, представляющие разные сценарии, которые затем будут сохранены в массиве scenarioListAll .

(Упрощенная) версия кода выглядит следующим образом:

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OverallManager2 : MonoBehaviour
{

public static object[] scenarioListAll = new object[40];

public class Scenario
{
    public string scenarioDesc;
    public bool surprise;     // The 'surprise' bool I want to reference is defined here
    public string surpriseType;
    public int[] leftOption;
    public int[] rightOption;
    public int scenarioNumber;

    public Scenario(string st, bool sp, int[] l, int[] r, int n)
    {
        scenarioDesc = st;
        surprise = sp;
        leftOption = l;
        rightOption = r;
        scenarioNumber = n;
    }

    // I haven't used this, but I'm not sure if this matters so I'm including this too
    public Scenario(string st, bool sp, string spt, int[] l, int[] r, int n)
    {
        scenarioDesc = st;
        surprise = sp;
        surpriseType = spt;
        leftOption = l;
        rightOption = r;
        scenarioNumber = n;
    }
}


public static int[] getArray(int a, int b, int c, int d, int e, int f)
{
    int[] arr = new int[6] {a, b, c, d, e, f};
    return arr;
}


// Storing scenarios, am looking for the bool (2nd position)
public Scenario s1 = new Scenario("Test1", false, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 1);
public Scenario s2 = new Scenario("Test2", true, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 2);
public Scenario s3 = new Scenario("Test3", false, getArray(1, 1, 1, 1, 1, 1), getArray(1, 1, 1, 1, 1, 1), 3);

    void Awake()
    {
        // Store scenarios in object array
        scenarioListAll[0] = s1;
        scenarioListAll[1] = s2;
        scenarioListAll[2] = s3;

        for(int i = 0; i < 40; i  )
        {
            object temp = scenarioListAll[i];     // Trying to extract the object stored in the array in a temp object
            bool surpriseCheck = temp.surprise;     // I am having problems with this line
            if(surpriseCheck == true)
            {
                // Do something
            }
        }
    }
// Ignoring start and update since they're irrelevant in this context
}
  

Что я хотел бы сделать, так это проверить, является ли surprise элемент в недавно определенном сценарии (например s1 ) истинным. Для этого я планировал извлечь сценарий, хранящийся в массиве scenarioListAll , а затем извлечь surprise оттуда компонент. Однако я не мог понять, как это сделать (например, в коде, показанном выше, он возвращает ошибку компилятора CS1061).

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

Спасибо за ваше время. Ваша помощь очень ценится.

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

1. object не имеет .surprise свойства. Возможно, вам следует определить массив как public static Scenario[] scenarioListAll и temp как Scenario temp = scenarioListAll[i]; ? Почему вы используете object в этих случаях?

2. Извините @Rufus L, я виноват в этом. Я не понимал, что могу использовать массивы Scenario напрямую. Проблема решена, несмотря ни на что, спасибо за ввод.

Ответ №1:

У вас возникла проблема с компиляцией из-за того, что компилятор c # не знает, что temp — это сценарий, поскольку вы объявили его как «объект». Если вы хотите перебрать сценарии и проверить, не являются ли они сюрпризом, вы можете использовать что-то вроде этого:

  foreach(Scenario temp in scenarioListAll)
 {
        bool surpriseCheck = temp.surprise;     
        if(surpriseCheck == true)
        {
            // Do something
        }
 }
  

Другим способом выполнения той же задачи с большим контролем над итерацией было бы:

  for(int i = 0; i < scenarioListAll.Length; i  )
 {
        Scenario temp = scenarioListAll[i];
        bool surpriseCheck = temp.surprise;     
        if(surpriseCheck == true)
        {
            // Do something
        }
 }
  

Преимущество первой версии в том, что вам не нужно беспокоиться о превышении границ массива. Как добавил Майк ниже, вы также можете использовать var, чтобы компилятор заполнял тип для вас.

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

1. foreach это ДАЛЕКО от синтаксического сахара. Это две ОЧЕНЬ разные вещи. for Оператор определяет разделы инициализатора, условия и итератора и выполняет блок кода, пока условие истинно. foreach с другой стороны, выполняет блок кода для каждого элемента в экземпляре типа, который реализует Систему. Коллекции. IEnumerable или System. Коллекции. Общий. Интерфейс IEnumerable<T> .

2. @Immersive На самом деле это неверно, InvalidCastException вместо этого будет выбрано a . foreach это просто ярлык для IEnumerable обработки.

3. @imsmn Хм, так кажется. Я не уверен, откуда я взял эту идею… :/

4. Я обновил сообщение, потому что я был неправ в том, что это синтаксический сахар. Я думаю, что я путаю java и .net, когда я переключаюсь между ними.

Ответ №2:

Иногда проще всего позволить компилятору определять тип переменной для нас.

В вашем случае вы указали, что переменная temp будет иметь тип object . Теперь это нормально, но в то время как a Scenario является производным от object , и object является классом самого низкого уровня в .Сетевая среда, и не является Scenario .

var Ключевое слово не означает, что объявленный тип имеет тип «переменной», вместо этого оно сообщает компилятору просто «заполнить» правильный тип, основываясь на предпринимаемых вами действиях. Итак, чтобы применить это к действию в вашем случае, вы могли бы сделать это вместо этого:

     for( var i = 0; i < 40; i   )                   // notice the use of var here as well
    {
        var scenario = scenarioListAll[i];          // renamed temp to scenario
        // var surpriseCheck = scenario .surprise;  // var used but line not required
        if( scenario.surprise )
        {
            // Do something
        }
    }
  

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

В вашем случае ваша следующая проблема будет заключаться в том, что вы определили массив как содержащий 40 object элементов, но затем вы создали только 3 Scenario элемента (что допустимо, но, вероятно, не совсем то, что вы хотите в целом). Итак, ваш код в его нынешнем виде приведет к ошибке NullReference. Вы сможете избежать этого с небольшой модификацией, чтобы ваш исправленный код мог выглядеть следующим образом, чтобы включить некоторые проверки типов:

 for( var i = 0; i < scenarioListAll.Length; i   )
{
    // First, check to see if the object in the array cell is a Scenario.
    // If the item in the cell is a Scenario, check to see if surprise is set.
    if ( scenarioListAll[i] is Scenario scenario amp;amp; scenario.surprise )
    {
        // Do something
    }
}
  

для получения дополнительной информации о is ключевом слове ознакомьтесь с документами Microsoft здесь .