none
приведение типа Object к заранее неизвестному типу RRS feed

  • Вопрос

  • Здравствуйте. VS2010, C++/CLR Console project
            //работает
    	array<int>^ MyArray = gcnew array<int>{1,2,3,4,5};
    	Object^ MyObject = MyArray;
    	int MyLength = (array<int>(MyObject))->Length;
    	Type^ MyArrayType = MyArray->GetType(); //System.Int32[]
    Type^ MyObjectType = MyObject->GetType; //System.Int32[] //не работает MyLength = (MyArrayType(MyObject))->Length; //ни так
    MeLength = (MyObjectType(MyObject))->Length;//ни так

    Я создаю массив array<int> и объект Object^ MyObject.
    затем MyObject становится как бы массивом MyObject = MyArray;
    и теперь я хочу узнать длину массива, но узнать через MyObject.

    вот так работает 
    int MyLength = (array<int>(MyObject))->Length;
    но если я знаю какого типа у меня объект?
    допусти это будет array<double>, array<char> и так далее.
    т.е. нужно чтобы Object  приводился к типу, который я узнаю по ходу дела.
    9 апреля 2013 г. 16:51

Ответы

  • Ок, вы приведете объект к заранее неизвестному типу. И что дальше? Вы же не можете в коде объявить переменную заранее неизвестного типа, которой присвоите результат приведения.
    9 апреля 2013 г. 17:34
    Модератор
  • А как компилятор должен будет на такое реагировать? Откуда он узнает, что у объекта есть свойство Length? Если Вы хотите вызывать свойства и методы по их имени, то Вам прямая дорога в Reflection.


    9 апреля 2013 г. 17:28
  • Делайте один и храните их как object, но при извлечении же вы всё равно уже должны знать с чем будете работать, делайте явное приведение типа и всё. Когда вы запрашваете конкретный объект, скажет тот же network, вы уже знаете что вы хотите. А если не знаете, что именно хотите, то иделать, выходит, ничего не нужно.
    9 апреля 2013 г. 19:37
    Модератор

Все ответы

  • int MyLength = ((Array^)MyObject)->Length;
    

    9 апреля 2013 г. 17:14
    Модератор
  • та нет же.
    нужно чтобы Object приводился к типу, который заранее неизвестен.
    там может быть Array, List, или просто String^.
    Смысл в том, чтобы приводить Object к типу Type
    9 апреля 2013 г. 17:23
  • А как компилятор должен будет на такое реагировать? Откуда он узнает, что у объекта есть свойство Length? Если Вы хотите вызывать свойства и методы по их имени, то Вам прямая дорога в Reflection.


    9 апреля 2013 г. 17:28
  • Ок, вы приведете объект к заранее неизвестному типу. И что дальше? Вы же не можете в коде объявить переменную заранее неизвестного типа, которой присвоите результат приведения.
    9 апреля 2013 г. 17:34
    Модератор
  • допустим
    есть словарь
    Dictionary<String^, Tuple<String^, Object^>^>

    Я кидаю в словарь 
    int a = 4;
    array<char>^ MyArray = gcnew array<char>{1, 2 ,3};
    MyDictionary->Add("Инт", (a->GetType, a));
    MyDictionary->Add("Массив", (MyArray->GetType, MyArray));

    и теперь я хочу обратиться к элементу словаря по ключу "Массив"
    и присовить всем элементам МАССИВА В СЛОВАРЕ значения переменной ИЗ СЛОВАРЯ по ключу "Инт"

    я не могу сделать так
    MyDictionary["Массив"][i]=MyDictionary["Инт"] 

    будет ошибка, так как у Объекта нету индексов.
    нужно взять
    MyDictionary["Массив"]->GetType

    и (это в случае примера будет System.Int32[] )
    и привести MyDictionary["Массив"] к типу System.Int32[] и уже работать с элементом словаря как с массивом.

    • Изменено Demaunt 9 апреля 2013 г. 17:57
    9 апреля 2013 г. 17:49
  • Array^ a=(Array^)MyDictionary["Массив"];
    Object^ b=MyDictionary["Инт"];
    ...
    a->SetValue(b,i);
    
    9 апреля 2013 г. 18:02
  • можно ли вместо 
    (Array ^)MyDictionary["Массив"]

    сделать типо
    (MyDictionary["Массив"]->GetType)MyDictionary["Массив"]
    в ответе там заранее известно что приводим к типу Array, а нужно узнать тип элемента в словаре(который будет System.Int32, не Object)
    и потом через приведение типов напрямую работать с элементом словаря как с массивом(а не как с Object)

    • Изменено Demaunt 9 апреля 2013 г. 18:19
    9 апреля 2013 г. 18:17
  • Напишите пример кода как вы хотите "напрямую работать с элементом словаря как с массивом", не зная что это именно массив Int32.

    Т.е. например у вас сработала строчка someUnknownTypedObject = (MyDictionary["Массив"]->GetType)MyDictionary["Массив"]; 

    Что вы дальше с ним в коде собираетесь делать (учитывая, что вы ничего о типе someUnknownTypedObject) при написании кода не знаете. Т.е. не можете даже заранее предположить, что это массив.

    9 апреля 2013 г. 18:40
    Модератор
  • Я к тому, что если вы будете работать "как с массивом" - то у вас где-то в коде должен быть каст к массиву. Например:

    	array<int>^ MyArray = gcnew array<int>{1,2,3,4,5};
    	Object^ MyObject = MyArray;
    
    	if (Array::typeid->IsAssignableFrom(MyObject->GetType()))
    	{
    		// массив
    		int myLength = ((Array^)MyObject)->Length;
    		Console::WriteLine(myLength);
    
    		if (MyObject->GetType() == array<int>::typeid)
    		{
    			// массив целых
    			int first = ((array<int>^)MyObject)[0];
    			Console::WriteLine(first);
    		}
    	}
    

    9 апреля 2013 г. 18:49
    Модератор
  •  можно ли каст к мaссиву, заменить на каст к getType. 
    // массив целых
    			int first = (MyArray->GetType())MyObject)[0];
    			Console::WriteLine(first);


    9 апреля 2013 г. 19:04
  • Нет, естественно. C++ - строготипизированный язык. Если в коде написано что-то-там[] - то компилятор дожен быть уверен, что у этого чего-то-там есть []. Если нужна динамическая типизация (можно писать все, во время выполнения упадет если что-то не так) - то пишите на другом языке. На C# с использованием dynamic. Или на javascript.
    9 апреля 2013 г. 19:08
    Модератор
  • Подобное в реальных программах вообще не должно наблюдатья, инача вопрос в правильности архитектуры приложения. В C# подобную проблему можно частично решить используя dynamic, как и в других динамических языках. Но это не решает проблему полностью, так как во время использования вы должны уже знать с чем и как вы работаете. Если очень и очень нужно, можно проанализировать объект используя рефлексию (анализируя на предмет нужных свойств и т.п.), как было сказано высше, но это уже в исключительных случаях. Думаю в данном случае у вас интерес академический, нежели практический.
    9 апреля 2013 г. 19:17
    Модератор
  • Ну интерес вот в чем.
    Есть например программа MatLab.
    Я импортирую данные.
    Там данные разных типов
    1x1 network (это объект класса Нейронная сеть)
    100x10 double (какой-то массив с данным)
    1x1 Info 
    и так далее.

    Допустим, я делаю программу.
    импортирую в нее данные разных типов, и складирую в Словарь, чтобы иметь доступ в дальнейшем.
    Я же не могу сделать отдельный словарь для каждого типа данных
    Я думал сделать словарь в который можно кидать объекты пользовательских классов ну и всякие массивы.

    Но получается, что придется делать словарь для массивов(входные данные).
    И словарь для выходных данных(допустим нейронная сеть, и другие классы) причем все классы, которые я буду ложить в словарь выходных данных, будут наследоваться от какого-то своего базового класса. Которые уже потом буду кастить в тип наследника
    9 апреля 2013 г. 19:27
  • Делайте один и храните их как object, но при извлечении же вы всё равно уже должны знать с чем будете работать, делайте явное приведение типа и всё. Когда вы запрашваете конкретный объект, скажет тот же network, вы уже знаете что вы хотите. А если не знаете, что именно хотите, то иделать, выходит, ничего не нужно.
    9 апреля 2013 г. 19:37
    Модератор