Delegaty i wyrażenia lambda

0

W jakich sytuacjach powinno się używać delegatów ,wyrażeń lambda oraz LINQ a w jakich lepiej nie? Zacząłem się tego uczyć i nie mogę znaleźć odpowiedzi na moje pytanie.

0

Jeśli chcesz użyć metody, która przyjmuje delegat albo wyrażenie lambda, to powinieneś ich użyć.
LINQ używamy do przeszukiwania, a także robienia projekcji oraz agregacji na kolekcjach.

1

Jest tylko jeden wyjątek kiedy nie należy używać LINQ. LINQ ma swój narzut pod względem wydajności i alokacji pamięci, także jak chcemy zoptymalizować dany fragment kodu wtedy unikamy w nim LINQ jak i wszelkich zbędnych alokacji zarządzanej pamięci.

1

Zacząłem się tego uczyć i nie mogę znaleźć odpowiedzi na moje pytanie.

To normalne. Uczysz sie mechanizmow jezyka, ale w wielu przypadkach nie bedziesz widzial sensu zastosowania ich dopoki nie pojawi sie taka potrzeba. Warto miec to na uwadze, bo rzeczy ktore sie uczysz predzej czy pozniej zaczna nabierac sensu i stawac sie przydatne.

Co do LINQ, to jesli jeszcze tego nie wiesz sa dwa sposoby pisania- syntakst zapytan (query syntax) vs metody (method syntax). Query syntax pozwala na mniej, ale jesli wierzyc Microsoftowi to wiekszosc ludzi uwaza go za latwiejszy do zrozumienia. Ja wrecz przeciwnie. Przy uzyciu LINQ (w tym przykladzie method syntax), mozemy np. wyciagnac liczby wieksze niz 10 z kolekcji w taki sposob:

var numbers = new List<int> { 2, 8, 11, 15 };
var foundNumbers = numbers.Where(n => n > 10);// Zwroci 11, 15 
0

Odkopuję temat! ;P
przepracowałem 2 lata w korpo, tworzyliśmy duże i małe webservice i na oczy nie zobaczyłem ani jednego delegata.
zamiast tego korzystaliśmy z mnóstwa frameworków wspierających.
Jest możliwe, że to wszystko było nam zdjęte z oczu, żeby tych delegatów nie pisać?
Byłem tydzień temu na rozmowie w dużej firmie na literkę 'M' i tam mnie też maglowali z delegatów i eventów, a moja wiedza praktyczna jest malutka z tej dziedziny.
No i dostałem feedback, że muszę się tego pouczyć (LOL)
No i teraz drążę ten temat i szukam faktycznie dużego rozwiązania biznesowego, które może praktycznie wykorzystywać delegaty.
Mnie wychowywali na zasadzie: nowa funkcjonalność - nowa klasa
a delegaty kuszą do łamania zasady Single Resposibility (przynajmniej takie mam wrażenie)
W czym to się przydaje?

1

Dynamic Query Building

Ogólnie delegaty to jakby wskaźniki na funkcje.

Action = void - użycie np. List.ForEach(x => Something(x))

Func<T, V> lub Func<A,B,C,D,E,T,...,V> = przyjmuje T(lub ABCDET...), zwraca V - używa się m.in w Linq np. Select

Predicate = zwraca boola, ale czasem(chyba częściej) też używa się Func<T, bool> - używa się m.in w Linq np. Where

np. libka taka jak Fluent Validation z tego mocno korzysta.

public IRuleBuilderInitial<T, TProperty> RuleFor<TProperty>(Expression<Func<T, TProperty>> expression)

public IConditionBuilder When(Func<T, bool> predicate, Action action)
0
leggo napisał(a):

Odkopuję temat! ;P
przepracowałem 2 lata w korpo, tworzyliśmy duże i małe webservice i na oczy nie zobaczyłem ani jednego delegata.
zamiast tego korzystaliśmy z mnóstwa frameworków wspierających.
Jest możliwe, że to wszystko było nam zdjęte z oczu, żeby tych delegatów nie pisać?

Jak to jest możliwe.? O_o

1

Delegatów używa się wtedy kiedy trzeba przekazać gdzieś funkcję. Może być to na przykład parser pliku CSV który będzie generycznie obsługiwał każdy typ jaki będziesz u siebie musiał obsłużyć. Parser będzie definiować tylko logikę obsługi csv-ki, natomiast samą projekcję do konkretnego typu przekażesz jako parametr metody.
Pseudokod:


    public class Order
    {
        public Order(int id, decimal value)
        {
            Id = id;
            Value = value;
        }

        public int Id { get; }
        public decimal Value { get; }
    }

    public class CsvParser<T>
    { 
        public IEnumerable<T> Parse(string csv, Func<string[], T> func)
        {
            var result = new List<T>();

            //tutaj logika dotycząca odczytu wierszy

            var rows = new string[0];

            foreach (var row in rows)
            {
                try
                {
                    var splitted = row.Split(",");
                    var element = func(splitted);
                    result.Add(element);
                }
                catch
                {
                    continue;
                }
            }

            return result;
        }
    }

   
    public class OrdersImporter
    {
        private readonly CsvParser<Order> _orderParser;

        public OrdersImporter(CsvParser<Order> orderParser)
        {
            _orderParser = orderParser;
        }

        public IEnumerable<Order> Import(string csv)
        {
            Func<string[], Order> func = row =>
            {
                int id = int.Parse(row[0]);
                decimal value = decimal.Parse(row[1]);
                return new Order(id, value);
            };

            IEnumerable<Order> orders = _orderParser.Parse(csv, func);
            return orders;
        }
    }

Innym przykładem użycia delegata mogłaby być konieczność wykonania jakiejś akcji w odpowiedzi na event. Np wysłka emaila do użytkownika po wystąpieniu jakiegoś zdarzenia (np o określonej godzinie).

0

Tak wygląda klasa Delegate . Jak przeczytasz to wszystko zrozumiesz ;)

// System.Delegate
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Threading;


[Serializable]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
[__DynamicallyInvokable]
public abstract class Delegate : ICloneable, ISerializable
{
    [SecurityCritical]
    internal object _target;

    [SecurityCritical]
    internal object _methodBase;

    [SecurityCritical]
    internal IntPtr _methodPtr;

    [SecurityCritical]
    internal IntPtr _methodPtrAux;
  [__DynamicallyInvokable]
    public MethodInfo Method
    {
        [__DynamicallyInvokable]
        get
        {
            return GetMethodImpl();
        }
    }
  [__DynamicallyInvokable]
    public object Target
    {
        [__DynamicallyInvokable]
        get
        {
            return GetTarget();
        }
    }
    [SecuritySafeCritical]
    protected Delegate(object target, string method)
    {
        if (target == null)
        {
            throw new ArgumentNullException("target");
        }
        if (method == null)
        {
            throw new ArgumentNullException("method");
        }
        if (!BindToMethodName(target, (RuntimeType)target.GetType(), method, (DelegateBindingFlags)10))
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
        }
    }
    [SecuritySafeCritical]
    protected Delegate(Type target, string method)
    {
        if (target == null)
        {
            throw new ArgumentNullException("target");
        }
        if (target.IsGenericType && target.ContainsGenericParameters)
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_UnboundGenParam"), "target");
        }
        if (method == null)
        {
            throw new ArgumentNullException("method");
        }
        RuntimeType runtimeType = target as RuntimeType;
        if (runtimeType == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "target");
        }
        BindToMethodName(null, runtimeType, method, (DelegateBindingFlags)37);
    }

    private Delegate()
    {
    }
    [__DynamicallyInvokable]
    public object DynamicInvoke(params object[] args)
    {
        return DynamicInvokeImpl(args);
    }
    [SecuritySafeCritical]
    protected virtual object DynamicInvokeImpl(object[] args)
    {
        RuntimeMethodInfo runtimeMethodInfo = (RuntimeMethodInfo)RuntimeType.GetMethodBase(methodHandle: new RuntimeMethodHandleInternal(GetInvokeMethod()), reflectedType: (RuntimeType)GetType());
        return runtimeMethodInfo.UnsafeInvoke(this, BindingFlags.Default, null, args, null);
    }
    [SecuritySafeCritical]
    [__DynamicallyInvokable]
    public override bool Equals(object obj)
    {
        if (obj == null || !InternalEqualTypes(this, obj))
        {
            return false;
        }
        Delegate @delegate = (Delegate)obj;
        if (_target == @delegate._target && _methodPtr == @delegate._methodPtr && _methodPtrAux == @delegate._methodPtrAux)
        {
            return true;
        }
        if (_methodPtrAux.IsNull())
        {
            if (!@delegate._methodPtrAux.IsNull())
            {
                return false;
            }
            if (_target != @delegate._target)
            {
                return false;
            }
        }
        else
        {
            if (@delegate._methodPtrAux.IsNull())
            {
                return false;
            }
            if (_methodPtrAux == @delegate._methodPtrAux)
            {
                return true;
            }
        }
        if (_methodBase == null || @delegate._methodBase == null || !(_methodBase is MethodInfo) || !(@delegate._methodBase is MethodInfo))
        {
            return InternalEqualMethodHandles(this, @delegate);
        }
        return _methodBase.Equals(@delegate._methodBase);
    }

    /// <summary>Returns a hash code for the delegate.</summary>
    /// <returns>A hash code for the delegate.</returns>
    [__DynamicallyInvokable]
    public override int GetHashCode()
    {
        return GetType().GetHashCode();
    }
   [__DynamicallyInvokable]
    public static Delegate Combine(Delegate a, Delegate b)
    {
        if ((object)a == null)
        {
            return b;
        }
        return a.CombineImpl(b);
    }
    [ComVisible(true)]
    [__DynamicallyInvokable]
    public static Delegate Combine(params Delegate[] delegates)
    {
        if (delegates == null || delegates.Length == 0)
        {
            return null;
        }
        Delegate @delegate = delegates[0];
        for (int i = 1; i < delegates.Length; i++)
        {
            @delegate = Combine(@delegate, delegates[i]);
        }
        return @delegate;
    }
   [__DynamicallyInvokable]
    public virtual Delegate[] GetInvocationList()
    {
        return new Delegate[1]
        {
            this
        };
    }
  [SecuritySafeCritical]
    protected virtual MethodInfo GetMethodImpl()
    {
        if (_methodBase == null || !(_methodBase is MethodInfo))
        {
            IRuntimeMethodInfo runtimeMethodInfo = FindMethodHandle();
            RuntimeType runtimeType = RuntimeMethodHandle.GetDeclaringType(runtimeMethodInfo);
            if ((RuntimeTypeHandle.IsGenericTypeDefinition(runtimeType) || RuntimeTypeHandle.HasInstantiation(runtimeType)) && (RuntimeMethodHandle.GetAttributes(runtimeMethodInfo) & MethodAttributes.Static) == MethodAttributes.PrivateScope)
            {
                if (_methodPtrAux == (IntPtr)0)
                {
                    Type type = _target.GetType();
                    Type genericTypeDefinition = runtimeType.GetGenericTypeDefinition();
                    while (type != null)
                    {
                        if (type.IsGenericType && type.GetGenericTypeDefinition() == genericTypeDefinition)
                        {
                            runtimeType = (type as RuntimeType);
                            break;
                        }
                        type = type.BaseType;
                    }
                }
                else
                {
                    MethodInfo method = GetType().GetMethod("Invoke");
                    runtimeType = (RuntimeType)method.GetParameters()[0].ParameterType;
                }
            }
            _methodBase = (MethodInfo)RuntimeType.GetMethodBase(runtimeType, runtimeMethodInfo);
        }
        return (MethodInfo)_methodBase;
    }
    [SecuritySafeCritical]
    [__DynamicallyInvokable]
    public static Delegate Remove(Delegate source, Delegate value)
    {
        if ((object)source == null)
        {
            return null;
        }
        if ((object)value == null)
        {
            return source;
        }
        if (!InternalEqualTypes(source, value))
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
        }
        return source.RemoveImpl(value);
    }
   [__DynamicallyInvokable]
    public static Delegate RemoveAll(Delegate source, Delegate value)
    {
        Delegate @delegate = null;
        do
        {
            @delegate = source;
            source = Remove(source, value);
        }
        while (@delegate != source);
        return @delegate;
    }

      protected virtual Delegate CombineImpl(Delegate d)
    {
        throw new MulticastNotSupportedException(Environment.GetResourceString("Multicast_Combine"));
    }
    protected virtual Delegate RemoveImpl(Delegate d)
    {
        if (!d.Equals(this))
        {
            return this;
        }
        return null;
    }

    /// <summary>Creates a shallow copy of the delegate.</summary>
    /// <returns>A shallow copy of the delegate.</returns>
    public virtual object Clone()
    {
        return MemberwiseClone();
    }
 public static Delegate CreateDelegate(Type type, object target, string method)
    {
        return CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true);
    }

     public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase)
    {
        return CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true);
    }
    [SecuritySafeCritical]
    public static Delegate CreateDelegate(Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        if (target == null)
        {
            throw new ArgumentNullException("target");
        }
        if (method == null)
        {
            throw new ArgumentNullException("method");
        }
        RuntimeType runtimeType = type as RuntimeType;
        if (runtimeType == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
        }
        if (!runtimeType.IsDelegate())
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
        }
        Delegate @delegate = InternalAlloc(runtimeType);
        if ([email protected](target, (RuntimeType)target.GetType(), method, (DelegateBindingFlags)(0x1A | (ignoreCase ? 32 : 0))))
        {
            if (throwOnBindFailure)
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
            }
            @delegate = null;
        }
        return @delegate;
    }
    public static Delegate CreateDelegate(Type type, Type target, string method)
    {
        return CreateDelegate(type, target, method, ignoreCase: false, throwOnBindFailure: true);
    }
    public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase)
    {
        return CreateDelegate(type, target, method, ignoreCase, throwOnBindFailure: true);
    }
    [SecuritySafeCritical]
    public static Delegate CreateDelegate(Type type, Type target, string method, bool ignoreCase, bool throwOnBindFailure)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        if (target == null)
        {
            throw new ArgumentNullException("target");
        }
        if (target.IsGenericType && target.ContainsGenericParameters)
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_UnboundGenParam"), "target");
        }
        if (method == null)
        {
            throw new ArgumentNullException("method");
        }
        RuntimeType runtimeType = type as RuntimeType;
        RuntimeType runtimeType2 = target as RuntimeType;
        if (runtimeType == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
        }
        if (runtimeType2 == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "target");
        }
        if (!runtimeType.IsDelegate())
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
        }
        Delegate @delegate = InternalAlloc(runtimeType);
        if ([email protected](null, runtimeType2, method, (DelegateBindingFlags)(5 | (ignoreCase ? 32 : 0))))
        {
            if (throwOnBindFailure)
            {
                throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
            }
            @delegate = null;
        }
        return @delegate;
    }
 [MethodImpl(MethodImplOptions.NoInlining)]
    [SecuritySafeCritical]
    public static Delegate CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        if (method == null)
        {
            throw new ArgumentNullException("method");
        }
        RuntimeType runtimeType = type as RuntimeType;
        if (runtimeType == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
        }
        RuntimeMethodInfo runtimeMethodInfo = method as RuntimeMethodInfo;
        if (runtimeMethodInfo == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
        }
        if (!runtimeType.IsDelegate())
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
        }
        StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
        Delegate @delegate = CreateDelegateInternal(runtimeType, runtimeMethodInfo, null, (DelegateBindingFlags)132, ref stackMark);
        if ((object)@delegate == null && throwOnBindFailure)
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
        }
        return @delegate;
    }
 [__DynamicallyInvokable]
    public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method)
    {
        return CreateDelegate(type, firstArgument, method, throwOnBindFailure: true);
    }

     [MethodImpl(MethodImplOptions.NoInlining)]
    [SecuritySafeCritical]
    public static Delegate CreateDelegate(Type type, object firstArgument, MethodInfo method, bool throwOnBindFailure)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        if (method == null)
        {
            throw new ArgumentNullException("method");
        }
        RuntimeType runtimeType = type as RuntimeType;
        if (runtimeType == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
        }
        RuntimeMethodInfo runtimeMethodInfo = method as RuntimeMethodInfo;
        if (runtimeMethodInfo == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
        }
        if (!runtimeType.IsDelegate())
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
        }
        StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
        Delegate @delegate = CreateDelegateInternal(runtimeType, runtimeMethodInfo, firstArgument, DelegateBindingFlags.RelaxedSignature, ref stackMark);
        if ((object)@delegate == null && throwOnBindFailure)
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
        }
        return @delegate;
    }
  [__DynamicallyInvokable]
    public static bool operator ==(Delegate d1, Delegate d2)
    {
        return d1?.Equals(d2) ?? ((object)d2 == null);
    }
   [__DynamicallyInvokable]
    public static bool operator !=(Delegate d1, Delegate d2)
    {
        if ((object)d1 == null)
        {
            return (object)d2 != null;
        }
        return !d1.Equals(d2);
    }

    
    [SecurityCritical]
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        throw new NotSupportedException();
    }

    [SecurityCritical]
    internal static Delegate CreateDelegateNoSecurityCheck(Type type, object target, RuntimeMethodHandle method)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        if (method.IsNullHandle())
        {
            throw new ArgumentNullException("method");
        }
        RuntimeType runtimeType = type as RuntimeType;
        if (runtimeType == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
        }
        if (!runtimeType.IsDelegate())
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
        }
        Delegate @delegate = InternalAlloc(runtimeType);
        if ([email protected](target, method.GetMethodInfo(), RuntimeMethodHandle.GetDeclaringType(method.GetMethodInfo()), (DelegateBindingFlags)192))
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
        }
        return @delegate;
    }

    [SecurityCritical]
    internal static Delegate CreateDelegateNoSecurityCheck(RuntimeType type, object firstArgument, MethodInfo method)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }
        if (method == null)
        {
            throw new ArgumentNullException("method");
        }
        RuntimeMethodInfo runtimeMethodInfo = method as RuntimeMethodInfo;
        if (runtimeMethodInfo == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
        }
        if (!type.IsDelegate())
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
        }
        Delegate @delegate = UnsafeCreateDelegate(type, runtimeMethodInfo, firstArgument, (DelegateBindingFlags)192);
        if ((object)@delegate == null)
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
        }
        return @delegate;
    }


    [__DynamicallyInvokable]
    public static Delegate CreateDelegate(Type type, MethodInfo method)
    {
        return CreateDelegate(type, method, throwOnBindFailure: true);
    }

    [SecuritySafeCritical]
    internal static Delegate CreateDelegateInternal(RuntimeType rtType, RuntimeMethodInfo rtMethod, object firstArgument, DelegateBindingFlags flags, ref StackCrawlMark stackMark)
    {
        bool flag = (rtMethod.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN;
        bool flag2 = (rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN;
        if (flag | flag2)
        {
            RuntimeAssembly executingAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
            if (executingAssembly != null && !executingAssembly.IsSafeForReflection())
            {
                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", flag ? rtMethod.FullName : rtType.FullName));
            }
        }
        return UnsafeCreateDelegate(rtType, rtMethod, firstArgument, flags);
    }

    [SecurityCritical]
    internal static Delegate UnsafeCreateDelegate(RuntimeType rtType, RuntimeMethodInfo rtMethod, object firstArgument, DelegateBindingFlags flags)
    {
        Delegate @delegate = InternalAlloc(rtType);
        if (@delegate.BindToMethodInfo(firstArgument, rtMethod, rtMethod.GetDeclaringTypeInternal(), flags))
        {
            return @delegate;
        }
        return null;
    }

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    private extern bool BindToMethodName(object target, RuntimeType methodType, string method, DelegateBindingFlags flags);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    private extern bool BindToMethodInfo(object target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    private static extern MulticastDelegate InternalAlloc(RuntimeType type);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal static extern MulticastDelegate InternalAllocLike(Delegate d);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal static extern bool InternalEqualTypes(object a, object b);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    private extern void DelegateConstruct(object target, IntPtr slot);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal extern IntPtr GetMulticastInvoke();

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal extern IntPtr GetInvokeMethod();

    [MethodImpl(MethodImplOptions.InternalCall)]
    internal extern IRuntimeMethodInfo FindMethodHandle();

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal static extern bool InternalEqualMethodHandles(Delegate left, Delegate right);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal extern IntPtr AdjustTarget(object target, IntPtr methodPtr);

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal extern IntPtr GetCallStub(IntPtr methodPtr);

    [SecuritySafeCritical]
    internal virtual object GetTarget()
    {
        if (!_methodPtrAux.IsNull())
        {
            return null;
        }
        return _target;
    }

    [MethodImpl(MethodImplOptions.InternalCall)]
    [SecurityCritical]
    internal static extern bool CompareUnmanagedFunctionPtrs(Delegate d1, Delegate d2);
}
using System;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;
using System.Threading;

[Serializable]
[ComVisible(true)]
[__DynamicallyInvokable]
public abstract class MulticastDelegate : Delegate
{
    [SecurityCritical]
    private object _invocationList;

    [SecurityCritical]
    private IntPtr _invocationCount;

    protected MulticastDelegate(object target, string method)
        : base(target, method)
    {
    }
   protected MulticastDelegate(Type target, string method)
        : base(target, method)
    {
    }

    [SecuritySafeCritical]
    internal bool IsUnmanagedFunctionPtr()
    {
        return _invocationCount == (IntPtr)(-1);
    }

    [SecuritySafeCritical]
    internal bool InvocationListLogicallyNull()
    {
        if (_invocationList != null && !(_invocationList is LoaderAllocator))
        {
            return _invocationList is DynamicResolver;
        }
        return true;
    }

      [SecurityCritical]
    public override void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        int num = 0;
        object[] array = _invocationList as object[];
        if (array == null)
        {
            MethodInfo method = base.Method;
            if (!(method is RuntimeMethodInfo) || IsUnmanagedFunctionPtr())
            {
                throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
            }
            if (!InvocationListLogicallyNull() && !_invocationCount.IsNull() && !_methodPtrAux.IsNull())
            {
                throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
            }
            DelegateSerializationHolder.GetDelegateSerializationInfo(info, GetType(), base.Target, method, num);
            return;
        }
        DelegateSerializationHolder.DelegateEntry delegateEntry = null;
        int num2 = (int)_invocationCount;
        int num3 = num2;
        while (--num3 >= 0)
        {
            MulticastDelegate multicastDelegate = (MulticastDelegate)array[num3];
            MethodInfo method2 = multicastDelegate.Method;
            if (method2 is RuntimeMethodInfo && !IsUnmanagedFunctionPtr() && (multicastDelegate.InvocationListLogicallyNull() || multicastDelegate._invocationCount.IsNull() || multicastDelegate._methodPtrAux.IsNull()))
            {
                DelegateSerializationHolder.DelegateEntry delegateSerializationInfo = DelegateSerializationHolder.GetDelegateSerializationInfo(info, multicastDelegate.GetType(), multicastDelegate.Target, method2, num++);
                if (delegateEntry != null)
                {
                    delegateEntry.Entry = delegateSerializationInfo;
                }
                delegateEntry = delegateSerializationInfo;
            }
        }
        if (delegateEntry != null)
        {
            return;
        }
        throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
    }
 [SecuritySafeCritical]
    [__DynamicallyInvokable]
    public sealed override bool Equals(object obj)
    {
        if (obj == null || !Delegate.InternalEqualTypes(this, obj))
        {
            return false;
        }
        MulticastDelegate multicastDelegate = obj as MulticastDelegate;
        if ((object)multicastDelegate == null)
        {
            return false;
        }
        if (_invocationCount != (IntPtr)0)
        {
            if (InvocationListLogicallyNull())
            {
                if (IsUnmanagedFunctionPtr())
                {
                    if (!multicastDelegate.IsUnmanagedFunctionPtr())
                    {
                        return false;
                    }
                    return Delegate.CompareUnmanagedFunctionPtrs(this, multicastDelegate);
                }
                if (multicastDelegate._invocationList is Delegate)
                {
                    return Equals(multicastDelegate._invocationList);
                }
                return base.Equals(obj);
            }
            if (_invocationList is Delegate)
            {
                return _invocationList.Equals(obj);
            }
            return InvocationListEquals(multicastDelegate);
        }
        if (!InvocationListLogicallyNull())
        {
            if (!_invocationList.Equals(multicastDelegate._invocationList))
            {
                return false;
            }
            return base.Equals((object)multicastDelegate);
        }
        if (multicastDelegate._invocationList is Delegate)
        {
            return Equals(multicastDelegate._invocationList);
        }
        return base.Equals((object)multicastDelegate);
    }

    [SecuritySafeCritical]
    private bool InvocationListEquals(MulticastDelegate d)
    {
        object[] array = _invocationList as object[];
        if (d._invocationCount != _invocationCount)
        {
            return false;
        }
        int num = (int)_invocationCount;
        for (int i = 0; i < num; i++)
        {
            Delegate @delegate = (Delegate)array[i];
            object[] array2 = d._invocationList as object[];
            if ([email protected](array2[i]))
            {
                return false;
            }
        }
        return true;
    }

    [SecurityCritical]
    private bool TrySetSlot(object[] a, int index, object o)
    {
        if (a[index] == null && Interlocked.CompareExchange<object>(ref a[index], o, (object)null) == null)
        {
            return true;
        }
        if (a[index] != null)
        {
            MulticastDelegate multicastDelegate = (MulticastDelegate)o;
            MulticastDelegate multicastDelegate2 = (MulticastDelegate)a[index];
            if (multicastDelegate2._methodPtr == multicastDelegate._methodPtr && multicastDelegate2._target == multicastDelegate._target && multicastDelegate2._methodPtrAux == multicastDelegate._methodPtrAux)
            {
                return true;
            }
        }
        return false;
    }

    [SecurityCritical]
    private MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount, bool thisIsMultiCastAlready)
    {
        MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
        if (thisIsMultiCastAlready)
        {
            multicastDelegate._methodPtr = _methodPtr;
            multicastDelegate._methodPtrAux = _methodPtrAux;
        }
        else
        {
            multicastDelegate._methodPtr = GetMulticastInvoke();
            multicastDelegate._methodPtrAux = GetInvokeMethod();
        }
        multicastDelegate._target = multicastDelegate;
        multicastDelegate._invocationList = invocationList;
        multicastDelegate._invocationCount = (IntPtr)invocationCount;
        return multicastDelegate;
    }

    [SecurityCritical]
    internal MulticastDelegate NewMulticastDelegate(object[] invocationList, int invocationCount)
    {
        return NewMulticastDelegate(invocationList, invocationCount, thisIsMultiCastAlready: false);
    }

    [SecurityCritical]
    internal void StoreDynamicMethod(MethodInfo dynamicMethod)
    {
        if (_invocationCount != (IntPtr)0)
        {
            MulticastDelegate multicastDelegate = (MulticastDelegate)_invocationList;
            multicastDelegate._methodBase = dynamicMethod;
        }
        else
        {
            _methodBase = dynamicMethod;
        }
    }
   [SecuritySafeCritical]
    protected sealed override Delegate CombineImpl(Delegate follow)
    {
        if ((object)follow == null)
        {
            return this;
        }
        if (!Delegate.InternalEqualTypes(this, follow))
        {
            throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
        }
        MulticastDelegate multicastDelegate = (MulticastDelegate)follow;
        int num = 1;
        object[] array = multicastDelegate._invocationList as object[];
        if (array != null)
        {
            num = (int)multicastDelegate._invocationCount;
        }
        object[] array2 = _invocationList as object[];
        int num2;
        object[] array3;
        if (array2 == null)
        {
            num2 = 1 + num;
            array3 = new object[num2];
            array3[0] = this;
            if (array == null)
            {
                array3[1] = multicastDelegate;
            }
            else
            {
                for (int i = 0; i < num; i++)
                {
                    array3[1 + i] = array[i];
                }
            }
            return NewMulticastDelegate(array3, num2);
        }
        int num3 = (int)_invocationCount;
        num2 = num3 + num;
        array3 = null;
        if (num2 <= array2.Length)
        {
            array3 = array2;
            if (array == null)
            {
                if (!TrySetSlot(array3, num3, multicastDelegate))
                {
                    array3 = null;
                }
            }
            else
            {
                for (int j = 0; j < num; j++)
                {
                    if (!TrySetSlot(array3, num3 + j, array[j]))
                    {
                        array3 = null;
                        break;
                    }
                }
            }
        }
        if (array3 == null)
        {
            int num4;
            for (num4 = array2.Length; num4 < num2; num4 *= 2)
            {
            }
            array3 = new object[num4];
            for (int k = 0; k < num3; k++)
            {
                array3[k] = array2[k];
            }
            if (array == null)
            {
                array3[num3] = multicastDelegate;
            }
            else
            {
                for (int l = 0; l < num; l++)
                {
                    array3[num3 + l] = array[l];
                }
            }
        }
        return NewMulticastDelegate(array3, num2, thisIsMultiCastAlready: true);
    }

    [SecurityCritical]
    private object[] DeleteFromInvocationList(object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
    {
        object[] array = _invocationList as object[];
        int num = array.Length;
        while (num / 2 >= invocationCount - deleteCount)
        {
            num /= 2;
        }
        object[] array2 = new object[num];
        for (int i = 0; i < deleteIndex; i++)
        {
            array2[i] = invocationList[i];
        }
        for (int j = deleteIndex + deleteCount; j < invocationCount; j++)
        {
            array2[j - deleteCount] = invocationList[j];
        }
        return array2;
    }

    private bool EqualInvocationLists(object[] a, object[] b, int start, int count)
    {
        for (int i = 0; i < count; i++)
        {
            if (!a[start + i].Equals(b[i]))
            {
                return false;
            }
        }
        return true;
    }
 [SecuritySafeCritical]
    protected sealed override Delegate RemoveImpl(Delegate value)
    {
        MulticastDelegate multicastDelegate = value as MulticastDelegate;
        if ((object)multicastDelegate == null)
        {
            return this;
        }
        if (!(multicastDelegate._invocationList is object[]))
        {
            object[] array = _invocationList as object[];
            if (array == null)
            {
                if (Equals(value))
                {
                    return null;
                }
            }
            else
            {
                int num = (int)_invocationCount;
                int num2 = num;
                while (--num2 >= 0)
                {
                    if (value.Equals(array[num2]))
                    {
                        if (num == 2)
                        {
                            return (Delegate)array[1 - num2];
                        }
                        object[] invocationList = DeleteFromInvocationList(array, num, num2, 1);
                        return NewMulticastDelegate(invocationList, num - 1, thisIsMultiCastAlready: true);
                    }
                }
            }
        }
        else
        {
            object[] array2 = _invocationList as object[];
            if (array2 != null)
            {
                int num3 = (int)_invocationCount;
                int num4 = (int)multicastDelegate._invocationCount;
                for (int num5 = num3 - num4; num5 >= 0; num5--)
                {
                    if (EqualInvocationLists(array2, multicastDelegate._invocationList as object[], num5, num4))
                    {
                        if (num3 - num4 == 0)
                        {
                            return null;
                        }
                        if (num3 - num4 == 1)
                        {
                            return (Delegate)array2[(num5 == 0) ? (num3 - 1) : 0];
                        }
                        object[] invocationList2 = DeleteFromInvocationList(array2, num3, num5, num4);
                        return NewMulticastDelegate(invocationList2, num3 - num4, thisIsMultiCastAlready: true);
                    }
                }
            }
        }
        return this;
    }
   [SecuritySafeCritical]
    [__DynamicallyInvokable]
    public sealed override Delegate[] GetInvocationList()
    {
        object[] array = _invocationList as object[];
        Delegate[] array2;
        if (array == null)
        {
            array2 = new Delegate[1]
            {
                this
            };
        }
        else
        {
            int num = (int)_invocationCount;
            array2 = new Delegate[num];
            for (int i = 0; i < num; i++)
            {
                array2[i] = (Delegate)array[i];
            }
        }
        return array2;
    }
   [__DynamicallyInvokable]
    public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2)
    {
        return d1?.Equals(d2) ?? ((object)d2 == null);
    }
   [__DynamicallyInvokable]
    public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2)
    {
        if ((object)d1 == null)
        {
            return (object)d2 != null;
        }
        return !d1.Equals(d2);
    }
   [SecuritySafeCritical]
    [__DynamicallyInvokable]
    public sealed override int GetHashCode()
    {
        if (IsUnmanagedFunctionPtr())
        {
            return ValueType.GetHashCodeOfPtr(_methodPtr) ^ ValueType.GetHashCodeOfPtr(_methodPtrAux);
        }
        object[] array = _invocationList as object[];
        if (array == null)
        {
            return base.GetHashCode();
        }
        int num = 0;
        for (int i = 0; i < (int)_invocationCount; i++)
        {
            num = num * 33 + array[i].GetHashCode();
        }
        return num;
    }

    [SecuritySafeCritical]
    internal override object GetTarget()
    {
        if (_invocationCount != (IntPtr)0)
        {
            if (InvocationListLogicallyNull())
            {
                return null;
            }
            object[] array = _invocationList as object[];
            if (array != null)
            {
                int num = (int)_invocationCount;
                return ((Delegate)array[num - 1]).GetTarget();
            }
            Delegate @delegate = _invocationList as Delegate;
            if ((object)@delegate != null)
            {
                return @delegate.GetTarget();
            }
        }
        return base.GetTarget();
    }
  [SecuritySafeCritical]
    protected override MethodInfo GetMethodImpl()
    {
        if (_invocationCount != (IntPtr)0 && _invocationList != null)
        {
            object[] array = _invocationList as object[];
            if (array != null)
            {
                int num = (int)_invocationCount - 1;
                return ((Delegate)array[num]).Method;
            }
            MulticastDelegate multicastDelegate = _invocationList as MulticastDelegate;
            if ((object)multicastDelegate != null)
            {
                return multicastDelegate.GetMethodImpl();
            }
        }
        else if (IsUnmanagedFunctionPtr())
        {
            if (_methodBase == null || !(_methodBase is MethodInfo))
            {
                IRuntimeMethodInfo runtimeMethodInfo = FindMethodHandle();
                RuntimeType runtimeType = RuntimeMethodHandle.GetDeclaringType(runtimeMethodInfo);
                if (RuntimeTypeHandle.IsGenericTypeDefinition(runtimeType) || RuntimeTypeHandle.HasInstantiation(runtimeType))
                {
                    RuntimeType runtimeType2 = GetType() as RuntimeType;
                    runtimeType = runtimeType2;
                }
                _methodBase = (MethodInfo)RuntimeType.GetMethodBase(runtimeType, runtimeMethodInfo);
            }
            return (MethodInfo)_methodBase;
        }
        return base.GetMethodImpl();
    }

    [DebuggerNonUserCode]
    private void ThrowNullThisInDelegateToInstance()
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst"));
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorClosed(object target, IntPtr methodPtr)
    {
        if (target == null)
        {
            ThrowNullThisInDelegateToInstance();
        }
        _target = target;
        _methodPtr = methodPtr;
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorClosedStatic(object target, IntPtr methodPtr)
    {
        _target = target;
        _methodPtr = methodPtr;
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorRTClosed(object target, IntPtr methodPtr)
    {
        _target = target;
        _methodPtr = AdjustTarget(target, methodPtr);
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk)
    {
        _target = this;
        _methodPtr = shuffleThunk;
        _methodPtrAux = methodPtr;
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorSecureClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
    {
        MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
        multicastDelegate.CtorClosed(target, methodPtr);
        _invocationList = multicastDelegate;
        _target = this;
        _methodPtr = callThunk;
        _methodPtrAux = creatorMethod;
        _invocationCount = GetInvokeMethod();
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorSecureClosedStatic(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
    {
        MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
        multicastDelegate.CtorClosedStatic(target, methodPtr);
        _invocationList = multicastDelegate;
        _target = this;
        _methodPtr = callThunk;
        _methodPtrAux = creatorMethod;
        _invocationCount = GetInvokeMethod();
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorSecureRTClosed(object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
    {
        MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
        multicastDelegate.CtorRTClosed(target, methodPtr);
        _invocationList = multicastDelegate;
        _target = this;
        _methodPtr = callThunk;
        _methodPtrAux = creatorMethod;
        _invocationCount = GetInvokeMethod();
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorSecureOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
    {
        MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
        multicastDelegate.CtorOpened(target, methodPtr, shuffleThunk);
        _invocationList = multicastDelegate;
        _target = this;
        _methodPtr = callThunk;
        _methodPtrAux = creatorMethod;
        _invocationCount = GetInvokeMethod();
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk)
    {
        _target = this;
        _methodPtr = shuffleThunk;
        _methodPtrAux = GetCallStub(methodPtr);
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorSecureVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
    {
        MulticastDelegate multicastDelegate = Delegate.InternalAllocLike(this);
        multicastDelegate.CtorVirtualDispatch(target, methodPtr, shuffleThunk);
        _invocationList = multicastDelegate;
        _target = this;
        _methodPtr = callThunk;
        _methodPtrAux = creatorMethod;
        _invocationCount = GetInvokeMethod();
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorCollectibleClosedStatic(object target, IntPtr methodPtr, IntPtr gchandle)
    {
        _target = target;
        _methodPtr = methodPtr;
        _methodBase = GCHandle.InternalGet(gchandle);
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorCollectibleOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
    {
        _target = this;
        _methodPtr = shuffleThunk;
        _methodPtrAux = methodPtr;
        _methodBase = GCHandle.InternalGet(gchandle);
    }

    [SecurityCritical]
    [DebuggerNonUserCode]
    private void CtorCollectibleVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
    {
        _target = this;
        _methodPtr = shuffleThunk;
        _methodPtrAux = GetCallStub(methodPtr);
        _methodBase = GCHandle.InternalGet(gchandle);
    }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1