Общий интерфейс и интерфейс в качестве параметра типа [дубликат]

Атрибуты - это своего рода метаданные для классов тегов. Это часто используется в WinForms, например, чтобы скрыть элементы управления на панели инструментов, но может быть реализовано в вашем собственном приложении, чтобы позволить экземплярам разных классов вести себя определенным образом.

Начните с создания атрибута:

[AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
public class SortOrderAttribute : Attribute
{
    public int SortOrder { get; set; }

    public SortOrderAttribute(int sortOrder)
    {
        this.SortOrder = sortOrder;
    }
}

Все классы атрибутов должны иметь суффикс «Атрибут», который должен быть действительным. После этого создайте класс, который использует этот атрибут.

[SortOrder(23)]
public class MyClass
{
    public MyClass()
    {
    }
}

Теперь вы можете проверить определенный класс SortOrderAttribute (если он есть), выполнив следующее:

public class MyInvestigatorClass
{
    public void InvestigateTheAttribute()
    {
        // Get the type object for the class that is using
        // the attribute.
        Type type = typeof(MyClass);

        // Get all custom attributes for the type.
        object[] attributes = type.GetCustomAttributes(
            typeof(SortOrderAttribute), true);

        // Now let's make sure that we got at least one attribute.
        if (attributes != null && attributes.Length > 0)
        {
            // Get the first attribute in the list of custom attributes
            // that is of the type "SortOrderAttribute". This should only
            // be one since we said "AllowMultiple=false".
            SortOrderAttribute attribute = 
                attributes[0] as SortOrderAttribute;

            // Now we can get the sort order for the class "MyClass".
            int sortOrder = attribute.SortOrder;
        }
    }
}

Если вы хотите больше узнать об этом, вы всегда можете проверить MSDN , который имеет довольно хорошее описание. Надеюсь, это помогло вам!

5
задан Uwe Keim 24 March 2013 в 10:07
поделиться

2 ответа

Ну, вы должны сделать свои интерфейсы covarient:

interface IUser<out PostType>
{
    PostType Post { get; }
}

interface IPost<out UserType>
{
    UserType User { get;  }
}

См. http://msdn.microsoft.com/en-gb/library/ee207183.aspx http://msdn.microsoft.com/en-gb/library/dd799517.aspx

0
ответ дан Meirion Hughes 21 August 2018 в 03:39
поделиться

Я попытаюсь объяснить это с помощью простого примера. Предположим, что у вас есть еще один класс, реализующий IPost<User>:

class PicturePost : IPost<User>
{
    // Implementation
}

Тогда этот код не будет компилироваться:

    IUser<Post> user = new User();
    user.Post = new PicturePost();

Поскольку user.Post имеет конкретный класс Post, который не совместим с PicturePost (они являются братьями и сестрами).

Тогда представьте, что строка из вашего вопроса была успешно скомпилирована:

    // C# compiler is so kind today and it compiled this.
    IUser<IPost<User>> user = new User();

Поскольку user.Post теперь будет иметь тип IPost<User> вы потенциально будете кодировать такие строки:

    IUser<IPost<User>> user = new User();
    user.Post = new PicturePost();

И они будут компилироваться отлично, но вторая строка не сработает с ошибкой во время выполнения! Это связано с тем, что фактическим типом user.Post является Post, а не IPost или PicturePost.

Итак, для обеспечения безопасности типов компилятор C # запрещает компиляцию, если есть вероятность такого код, который нужно написать. Чтобы убедиться, что вы не будете писать такой код, свойство Post должно быть доступно только для чтения:

interface IUser<PostType>
{
    PostType Post { get; } // No setter, this is readonly.
}

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

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

interface IUser<out PostType>
{
    PostType Post { get; } // No setter, this is readonly.
}

    // Both lines compile!
    IUser<IPost<User>> user = new User();
    IUser<Post> user1 = new User();

Надеюсь, я оставил его простым и не упустил точку в то же время:)

12
ответ дан SergeyS 21 August 2018 в 03:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: