0 / 0 / 0
Регистрация: 12.06.2015
Сообщений: 14
1

Преобразование типов, являющихся наследниками Attribute

12.06.2015, 13:32. Показов 1106. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Столкнулся с такой проблемой. Читаю Шилдта и встретился мне такой пример:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
 
 
[AttributeUsage(AttributeTargets.All)]
public class RemarkAttribute: Attribute
{
    public string Remark { get; private set; }
 
    public RemarkAttribute(string str)
    {
        Remark = str;
    }
}
 
 
[RemarkAttribute("Ремарка от атрибута")]
class MyClass
{
}
 
 
class Example
{
    static void Main()
    {
        Type objForTypeMyClass = typeof(MyClass);
        Type objForTypeOfAttribute = typeof(RemarkAttribute);
 
        RemarkAttribute re = (RemarkAttribute) Attribute.GetCustomAttribute(objForTypeMyClass, objForTypeOfAttribute); // в этом месте непонятно
 
        
    }
}
В классе Example вызывается метод GetCustomAttribute, который возвращает объект типа Attribute. Но при этом данный объект преобразовывается в тип RemarkAttribute, являющийся производным для класса Attribute. Т.е. получается производный_класс = (производный_класс) базовый_класс. Как такое возможно? Поясните, пожалуйста.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.06.2015, 13:32
Ответы с готовыми решениями:

Преобразование типов в T
Доброго времени суток всем. Есть у меня List с заранее неизвестным типом <T> Так же есть строка...

Преобразование типов
Подскажите как в c# с массивом int можно поработать как с массивом byte; Как в с++, например, int...

Преобразование типов
Что-то совсем в тупик зашла.Как здесь явно преобразовать? public SortedDictionary<char, double>...

Преобразование типов
Подскажите, пожалуйста! Я не сильна в C#. Я ввожу в textBox любое отрицательное число....

12
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
12.06.2015, 13:44 2
Цитата Сообщение от razamanaz Посмотреть сообщение
получается производный_класс = (производный_класс) базовый_класс. Как такое возможно?
Вполне возможно. Это явное приведение типов.
Статический метод класса Attribute() GetCustomAttribute() имеет возвращаемый тип как Attribute() (то есть базовый тип для всех атрибутов).
А вы просто явно приводите его к типу-наследнику (вашему атрибуту). Для исключения ошибки желательно бы еще проверить полученное значение на null.
0
0 / 0 / 0
Регистрация: 12.06.2015
Сообщений: 14
12.06.2015, 13:50  [ТС] 3
Цитата Сообщение от insite2012 Посмотреть сообщение
Вполне возможно. Это явное приведение типов.
Статический метод класса Attribute() GetCustomAttribute() имеет возвращаемый тип как Attribute() (то есть базовый тип для всех атрибутов).
А вы просто явно приводите его к типу-наследнику (вашему атрибуту). Для исключения ошибки желательно бы еще проверить полученное значение на null.
А почему тогда такое творение не работает? И в чем разница между этими ситуациями?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
 
class A
{ }
 
class B:A
{ }
 
 
class Example
{
    static void Main()
    {
        A objA = new A();
        B objB = new B();
 
        objB = (B)objA;
    }
}
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
12.06.2015, 14:07 4
Лучший ответ Сообщение было отмечено razamanaz как решение

Решение

Цитата Сообщение от razamanaz Посмотреть сообщение
почему тогда такое творение не работает?
Почему не работает? Если говорить точно, оно работает, только выбрасывает InvalidCastException (как и должно быть). Вы просто не совсем поняли.
В первом случае возвращаемое значение является, во первых типом Attribute() (поскольку это возвращаемый тип данного метода). И во вторых, поскольку вы извлекаете свой атрибут, оно же является и вашим собственным типом. Если оно им не является - так же получите InvalidCastException. Для того чтобы этого не было, можно использовать кс is или as.
1
0 / 0 / 0
Регистрация: 12.06.2015
Сообщений: 14
12.06.2015, 14:18  [ТС] 5
Цитата Сообщение от insite2012 Посмотреть сообщение
Почему не работает? Если говорить точно, оно работает, только выбрасывает InvalidCastException (как и должно быть). Вы просто не совсем поняли.
В первом случае возвращаемое значение является, во первых типом Attribute() (поскольку это возвращаемый тип данного метода). И во вторых, поскольку вы извлекаете свой атрибут, оно же является и вашим собственным типом. Если оно им не является - так же получите InvalidCastException. Для того чтобы этого не было, можно использовать кс is или as.
Т.е. получается, что в возвращаемую переменную типа Attribute записывается адрес на переменную типа RemarkAttribute (что вполне допустимо),далее мы этот адрес передаем переменной re типа RemarkAttribute (все сходится). Я Вас правильно понимаю? Тогда возникает последний встречный вопрос: зачем выполнять явное приведение типов
RemarkAttribute re = (RemarkAttribute) Attribute.GetCustomAttribute(objForTypeMyClass, objForTypeOfAttribute);
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
12.06.2015, 14:23 6
Цитата Сообщение от razamanaz Посмотреть сообщение
последний встречный вопрос: зачем выполнять явное приведение типов
Какие адреса? Еще раз: возвращаемый тип у этого метода - System.Attribute(). Но поскольку ваш класс является его наследником, и вы именно его извлекаете, то в вашем случае возвращаемый тип-тип вашего класса. Но поскольку переменная возврата типа System.Attribute() (то есть базового типа, в которой скрыт ваш собственный тип), то необходимо ее явно привести к вашему типу.

Добавлено через 1 минуту
Вы можете и не приводить переменную, которую вам возвратил метод к вашему типу, но тогда она будет более "общего" типа System.Attribute().
0
Администратор
Эксперт .NET
9602 / 4744 / 761
Регистрация: 17.04.2012
Сообщений: 9,592
Записей в блоге: 14
12.06.2015, 14:24 7
razamanaz, ваш пример не соответствует ситуации по причине того, что Attribute.GetCustomAttribute() возвращает экземпляр класса RemarkAttribute, но приведённый к типу-родителю, т.е. Attribute
Вот такой код примерно повторяет код из первого сообщения
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
namespace Program
{
    class A
    { }
 
    class B:A
    { }
    
    class Program
    {
        static A Dummy(B obj) {
            return (A)obj;
        }
        
        static void Main() {
            A objA = new A();
            B objB = (B)Dummy(new B());
            Console.WriteLine(objB.GetType());
        }
    }
}
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
12.06.2015, 14:28 8
Цитата Сообщение от tezaurismosis Посмотреть сообщение
экземпляр класса RemarkAttribute, но приведённый к типу-наследнику, т.е. Attribute
Коллега, вы хотели сказать, к базовому типу, как я понимаю)))
1
tezaurismosis
12.06.2015, 14:43
  #9

Не по теме:

insite2012, ваша правда :) Сообщение исправил.

0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
12.06.2015, 14:49 10
razamanaz, просто поймите одну вещь. Когда разработчики писали FCL (и конкретно этот метод), они, естественно, не могли предугадать, какого типа будет возвращенная переменная. Именно потому они и сделали возвращаемый тип как System.Attribute(), как общий для всех атрибутов (как встроенных в FCL, так и пользовательских). А какой точно тип-известно тому, кто применяет этот метод.
И да, второй момент. Сам объект не меняется (применительно к вашему коду). Он остается тем же самым, но поскольку ссылка на него (именно ссылка, а не сам объект) имеет тип базового класса, то все, что определено в самом объекте и не относится к базовому типу, компилятор скрывает. Вам доступно только то, что есть в базовом классе. Все что есть в наследнике не пропадает, оно просто (до явного приведения типов) не видно. В конце концов, язык же со строгой типизацией, и компилятор за этим следит.
1
0 / 0 / 0
Регистрация: 12.06.2015
Сообщений: 14
12.06.2015, 14:56  [ТС] 11
Цитата Сообщение от razamanaz Посмотреть сообщение
Т.е. получается, что в возвращаемую переменную типа Attribute записывается адрес на переменную типа RemarkAttribute (что вполне допустимо),далее мы этот адрес передаем переменной re типа RemarkAttribute (все сходится).
По поводу приведения типов понял. Но непонятно, в чем ошибки моих процитированных размышлений?
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
12.06.2015, 14:59 12
Цитата Сообщение от razamanaz Посмотреть сообщение
в чем ошибки моих процитированных размышлений?
Во первых, зачем вы пытаетесь манипулировать понятие "адрес" В C# оно просто не нужно. Есть переменная, есть объект, и так далее. А какие у них адреса, и так далее-это уже не нужно.
Ну а суть я вам рассказал. Разницу между типом ссылки (указателя на объект) и типом самого объекта.
1
0 / 0 / 0
Регистрация: 12.06.2015
Сообщений: 14
12.06.2015, 15:02  [ТС] 13
Спасибо всем! Вообщем, думаю, что разобрался!
0
12.06.2015, 15:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.06.2015, 15:02
Помогаю со студенческими работами здесь

Преобразование типов
Всем привет есть вопросы по преобразованию типов точнее даже не знаю относиться ли эта проблема к...

Преобразование типов
Всем привет. Переношу код из сишной реализации в проект на C#. Есть функция подсчета CRC, при ее...

Преобразование типов
Как преобазовывать(копировать) ListBox.lines в List<string> Description = new List<string>(); и...

Преобразование типов
Всем привет, не получается преобразовать начальное значение т.е. инициализация переменной класса....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru