Расширение оператора ‹и› для System.Type

Возможный дубликат:
Перегрузка оператора с расширением C # Методы

Как я могу перегрузить эти операторы, я чувствую, что компилятор неправильно понял их.

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

    public static class TypeCheck
    {
        public static Boolean ToBool(this Type t1, Type t2)
        {
            //normal extension works
            return true;
        }

        public static Boolean operator > (this Type t1, Type t2)
        {
            //TODO once it compiles
            return fasle;
        }

        public static Boolean operator < (this Type t1, Type t2)
        {
            //TODO once it compiles
            return true;
        }

    }

Чтобы прояснить специфику предметной области этих сравнений: class A : B {}, class B {} и class C {} A больше, чем A, и больше, чем B, но меньше, чем остальные. Поскольку A.IsCastableTo (B) и A.IsCastableTo (A);


person Johannes    schedule 12.03.2012    source источник
comment
Здесь вы найдете ответ http://stackoverflow.com/questions/172658/operator-overloading-with-c-sharp-extension-methods   -  person mimo    schedule 12.03.2012
comment
Я даже не понимаю, как один Тип может быть ›или‹ другого.   -  person cadrell0    schedule 12.03.2012
comment
@ cadrell0: Вы можете прочитать ‹as более узким или более конкретным, чем, например, if class B : A then B‹ A.   -  person dtb    schedule 12.03.2012
comment
Из этого не следует, как работают любые другие сравнения с ‹и›. 17 не более конкретен, чем 23. 01.01.2012 не более конкретен, чем 1 марта 2012 г. ASDF не более специфичен, чем QWER. Далее, что вернет C < B, если C определен как class C { }. И если вы скажете мне, что он должен вернуть false, тогда я ожидаю, что либо C > B, либо C == B вернут true.   -  person cadrell0    schedule 12.03.2012
comment
Я использую cadrell0, какой здесь вариант использования? Что-то пахнет ...   -  person NotMe    schedule 12.03.2012
comment
@ cadrell0: Очевидно, это частичный заказ. И я согласен, что использовать для этого стандартные операторы ‹› сомнительно; Я просто пытался указать, что можно определить порядок по типам.   -  person dtb    schedule 12.03.2012
comment
Мой проект зависит от нескольких проверок типов в разных частях системы - мне нужен был способ собрать эту ответственность в одном месте. В настоящее время проверка типов выполняется в нескольких подфункциях, которые вызываются в операторах if. Используя оператор bool, я хочу избавиться от методов, не меняя фрейм этих операторов if. Я сейчас занимаюсь рефакторингом ... так что, может быть, в конце я сделаю что-нибудь другое.   -  person Johannes    schedule 12.03.2012


Ответы (4)


arrow_upward
1
arrow_downward

Как уже говорили другие, C # не поддерживает операторы расширения. Если вам нужно это сделать, вы можете реализовать собственный тип, например:

public class MyType : Type
{
    private Type internalType;

    public MyType(Type t)
    {
        internalType = t;
    }

    public static Boolean operator >(MyType t1, Type t2)
    {
        //TODO once it compiles
        return false;
    }

    public static Boolean operator <(MyType t1, Type t2)
    {
        //TODO once it compiles
        return true;
    }

    public override Assembly Assembly
    {
        get { return internalType.Assembly; }
    }

    public override string AssemblyQualifiedName
    {
        get { return internalType.AssemblyQualifiedName; }
    }

    public override Type BaseType
    {
        get { return internalType.BaseType; }
    }

    public override string FullName
    {
        get { return internalType.FullName; }
    }

    public override Guid GUID
    {
        get { return internalType.GUID; }
    }

    protected override TypeAttributes GetAttributeFlagsImpl()
    {
        return internalType.Attributes;
    }

    protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
    {
        return internalType.GetConstructor(bindingAttr, binder, callConvention, types, modifiers);
    }

    public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
    {
        return internalType.GetConstructors(bindingAttr);
    }

    public override Type GetElementType()
    {
        return GetElementType();
    }

    public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
    {
        return internalType.GetEvent(name, bindingAttr);
    }

    public override EventInfo[] GetEvents(BindingFlags bindingAttr)
    {
        return internalType.GetEvents(bindingAttr);
    }

    public override FieldInfo GetField(string name, BindingFlags bindingAttr)
    {
        return internalType.GetField(name, bindingAttr);
    }

    public override FieldInfo[] GetFields(BindingFlags bindingAttr)
    {
        return internalType.GetFields(bindingAttr);
    }

    public override Type GetInterface(string name, bool ignoreCase)
    {
        return internalType.GetInterface(name, ignoreCase);
    }

    public override Type[] GetInterfaces()
    {
        return internalType.GetInterfaces();
    }

    public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
    {
        return internalType.GetMembers(bindingAttr);
    }

    protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
    {
        return internalType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
    }

    public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
    {
        return internalType.GetMethods(bindingAttr);
    }

    public override Type GetNestedType(string name, BindingFlags bindingAttr)
    {
        return internalType.GetNestedType(name, bindingAttr);
    }

    public override Type[] GetNestedTypes(BindingFlags bindingAttr)
    {
        return internalType.GetNestedTypes(bindingAttr);
    }

    public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
    {
        return internalType.GetProperties(bindingAttr);
    }

    protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
    {
        return internalType.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
    }

    protected override bool HasElementTypeImpl()
    {
        return internalType.HasElementType;
    }

    public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
    {
        return internalType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
    }

    protected override bool IsArrayImpl()
    {
        return internalType.IsArray;
    }

    protected override bool IsByRefImpl()
    {
        return internalType.IsByRef;
    }

    protected override bool IsCOMObjectImpl()
    {
        return internalType.IsCOMObject;
    }

    protected override bool IsPointerImpl()
    {
        return internalType.IsPointer;
    }

    protected override bool IsPrimitiveImpl()
    {
        return internalType.IsPrimitive;
    }

    public override Module Module
    {
        get { return internalType.Module; }
    }

    public override string Namespace
    {
        get { return internalType.Namespace; }
    }

    public override Type UnderlyingSystemType
    {
        get { return internalType.UnderlyingSystemType; }
    }

    public override object[] GetCustomAttributes(Type attributeType, bool inherit)
    {
        return internalType.GetCustomAttributes(attributeType, inherit);
    }

    public override object[] GetCustomAttributes(bool inherit)
    {
        return internalType.GetCustomAttributes(inherit);
    }

    public override bool IsDefined(Type attributeType, bool inherit)
    {
        return internalType.IsDefined(attributeType, inherit);
    }

    public override string Name
    {
        get { return internalType.Name; }
    }
}

В качестве альтернативы, вероятно, было бы проще реализовать собственный DynamicObject (C # 4+), который может делегировать вызовы.

person M.Babcock    schedule 12.03.2012

arrow_upward
7
arrow_downward

В C # нет «операторов расширения».

По крайней мере, один из параметров оператора должен быть того типа, в котором объявлен оператор.

person dtb    schedule 12.03.2012

arrow_upward
1
arrow_downward

Вы можете перегрузить операторы в ваших собственных классах, но не в других классах, используя подход метода расширения.

person Joshua Honig    schedule 12.03.2012

arrow_upward
1
arrow_downward

Вы не можете определять поведение операторов как методы расширения.
Вы можете сделать это так же, как DateTime работает с Add() и Subtract(), которые могут быть реализованы как методы расширения, если вы не можете изменить реализацию типов.

Вы также можете наследовать от типа (если возможно) и определять там операторы.

person Louis Kottmann    schedule 12.03.2012