Класс C# может наследовать атрибуты от своего интерфейса?

Что-нибудь мешает Java создать неявный конструктор копирования, который вызовет конструктор копирования для всех членов?

Главным образом тот факт, что это не то, что он должен делать.

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

Кроме того, добавление этого конструктора является еще одним методом: в средах, где важно количество методов (например, ограничение Android Dex в 64 тыс.), Вы платите за то, что вам не нужно.

Лучше позволить вам сделать это, если вам это нужно, сделав это явным.


Но что мешает Java иметь это?

Учитывая, что вы можете определить конструктор копирования вручную, технически целесообразно добавить их автоматически.

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

Легко указать, что вам не нужен ctor по умолчанию: просто определите свой ctor с любой подписью. Но вы не могли бы сделать то же самое с копирующим ctor по умолчанию: по определению копирующий ctor всегда будет иметь только подпись YourClass(YourClass instance); таким образом, вы не можете требовать, скажем, чтобы вы определили явный ctor копирования, который выдает, потому что тогда вы изменили ошибку времени компиляции (такой ctor не существует) на ошибку времени выполнения (она существует, но выдает).

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

Это не невозможно в абсолютном смысле - но потребуется много работы, чтобы изменить язык, чтобы добавить функцию, которая может быть реализована в существующем языке.

110
задан chiccodoro 30 July 2014 в 09:02
поделиться

2 ответа

Нет. Реализовывая интерфейс или переопределяющих участников в производном классе, необходимо повторно объявить атрибуты.

, Если Вы только заботитесь о ComponentModel (не прямое отражение), существует путь ( [AttributeProvider] ) предложения атрибутов от существующего типа (для предотвращения дублирования), но это только допустимо для использования индексатора и свойства.

Как пример:

using System;
using System.ComponentModel;
class Foo {
    [AttributeProvider(typeof(IListSource))]
    public object Bar { get; set; }

    static void Main() {
        var bar = TypeDescriptor.GetProperties(typeof(Foo))["Bar"];
        foreach (Attribute attrib in bar.Attributes) {
            Console.WriteLine(attrib);
        }
    }
}

выводы:

System.SerializableAttribute
System.ComponentModel.AttributeProviderAttribute
System.ComponentModel.EditorAttribute
System.Runtime.InteropServices.ComVisibleAttribute
System.Runtime.InteropServices.ClassInterfaceAttribute
System.ComponentModel.TypeConverterAttribute
System.ComponentModel.MergablePropertyAttribute
67
ответ дан Marc Gravell 24 November 2019 в 03:16
поделиться

Вы можете определить полезный метод расширения ...

Type type = typeof(ProjectController);
var attributes = type.GetCustomAttributes<CustomDescriptionAttribute>( true );

Вот метод расширения:

/// <summary>Searches and returns attributes. The inheritance chain is not used to find the attributes.</summary>
/// <typeparam name="T">The type of attribute to search for.</typeparam>
/// <param name="type">The type which is searched for the attributes.</param>
/// <returns>Returns all attributes.</returns>
public static T[] GetCustomAttributes<T>( this Type type ) where T : Attribute
{
  return GetCustomAttributes( type, typeof( T ), false ).Select( arg => (T)arg ).ToArray();
}

/// <summary>Searches and returns attributes.</summary>
/// <typeparam name="T">The type of attribute to search for.</typeparam>
/// <param name="type">The type which is searched for the attributes.</param>
/// <param name="inherit">Specifies whether to search this member's inheritance chain to find the attributes. Interfaces will be searched, too.</param>
/// <returns>Returns all attributes.</returns>
public static T[] GetCustomAttributes<T>( this Type type, bool inherit ) where T : Attribute
{
  return GetCustomAttributes( type, typeof( T ), inherit ).Select( arg => (T)arg ).ToArray();
}

/// <summary>Private helper for searching attributes.</summary>
/// <param name="type">The type which is searched for the attribute.</param>
/// <param name="attributeType">The type of attribute to search for.</param>
/// <param name="inherit">Specifies whether to search this member's inheritance chain to find the attribute. Interfaces will be searched, too.</param>
/// <returns>An array that contains all the custom attributes, or an array with zero elements if no attributes are defined.</returns>
private static object[] GetCustomAttributes( Type type, Type attributeType, bool inherit )
{
  if( !inherit )
  {
    return type.GetCustomAttributes( attributeType, false );
  }

  var attributeCollection = new Collection<object>();
  var baseType = type;

  do
  {
    baseType.GetCustomAttributes( attributeType, true ).Apply( attributeCollection.Add );
    baseType = baseType.BaseType;
  }
  while( baseType != null );

  foreach( var interfaceType in type.GetInterfaces() )
  {
    GetCustomAttributes( interfaceType, attributeType, true ).Apply( attributeCollection.Add );
  }

  var attributeArray = new object[attributeCollection.Count];
  attributeCollection.CopyTo( attributeArray, 0 );
  return attributeArray;
}

/// <summary>Applies a function to every element of the list.</summary>
private static void Apply<T>( this IEnumerable<T> enumerable, Action<T> function )
{
  foreach( var item in enumerable )
  {
    function.Invoke( item );
  }
}

Обновление:

Вот более короткая версия, предложенная SimonD в комментарии:

private static IEnumerable<T> GetCustomAttributesIncludingBaseInterfaces<T>(this Type type)
{
  var attributeType = typeof(T);
  return type.GetCustomAttributes(attributeType, true).
    Union(type.GetInterfaces().
    SelectMany(interfaceType => interfaceType.GetCustomAttributes(attributeType, true))).
    Distinct().Cast<T>();
}
37
ответ дан 24 November 2019 в 03:16
поделиться
Другие вопросы по тегам:

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