Я уже выкладывал код данной монады в разделе "программирование". Однако Unity 5 имеет весьма специфичное сравнение с null для своих объектов, из-за чего тот код не совсем валиден.
Так скажем это "код с костылем".
using System.Collections; using System.Collections.Generic; using System.Linq; namespace System.Monads { /// <summary> Для словарей </summary> public static class MaybeIDictionary { /// <summary> Выполняет действие с каждым элементом словаря, если словарь существует </summary> public static IDictionary<TKey, TValue> Do<TKey, TValue>(this IDictionary<TKey, TValue> source, Action<TKey, TValue> action) { if (source != null) { foreach (var element in source) { action(element.Key, element.Value); } } return source; } /// <summary> Достает значение по указанному ключу, если словарь существует и имеет такой ключ. В противном случае возвращает значение типа по умолчанию. </summary> public static TValue With<TKey, TValue>(this IDictionary<TKey, TValue> source, TKey key) { if (source != null) { TValue result; if (source.TryGetValue(key, out result)) return result; } return default(TValue); } /// <summary> /// Достает значение по указанному ключу, если словарь существует и имеет такой ключ. В противном случае возвращает заданное нами значение по умолчанию </summary> public static TValue Return<TKey, TValue>(this IDictionary<TKey, TValue> source, TKey key, TValue defaultValue) { if (source != null) { TValue result; if (source.TryGetValue(key, out result)) return result; } return defaultValue; } } /// <summary> Для перечислений - массивы, списки </summary> public static class MaybeIEnumerable { /// <summary> Выполняет указанное действие с каждым элементом списка, если список существует </summary> public static IEnumerable Do(this IEnumerable source, Action<object> action) { var enumerable = source as object[] ?? source.Cast<object>().ToArray(); if (source != null) foreach (var element in enumerable) action(element); return enumerable; } /// <summary> Выполняет указанное действие с каждым элементом списка, если список существует </summary> public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> action) { var enumerable = source as TSource[] ?? source.ToArray(); if (source != null) foreach (var element in enumerable) action(element); return enumerable; } /// <summary> Выполняет указанное действие с каждым элементом списка, если список существует </summary> public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource, int> action) { var enumerable = source as TSource[] ?? source.ToArray(); if (source != null) foreach (var element in enumerable.Select((s, i) => new { Source = s, Index = i })) action(element.Source, element.Index); return enumerable; } /// <summary> Проталкивает указанное поле, если список существует. Аналог Select() грубо говоря </summary> public static IEnumerable<TResult> With<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> action) { return source != null ? source.Select(action) : null; } } public static class MaybeNullable { /// <summary> Выполняет указанное действие, если объект существует. </summary> public static TSource? Do<TSource>(this TSource? source, Action<TSource?> action) where TSource : struct { if (source.HasValue) action(source); return source; } /// <summary> Проталкивает указанное значение, если объект существует и значение типа по умолчанию, если не существует </summary> public static TResult With<TSource, TResult>(this TSource? source, Func<TSource?, TResult> action) where TSource : struct { return source.HasValue ? action(source) : default(TResult); } /// <summary> Проталкивает указанное значение, если объект существует и значение указанного нами типа, если не существует </summary> public static TResult Return<TSource, TResult>(this TSource? source, Func<TSource?, TResult> action, TResult defaultValue) where TSource : struct { return source.HasValue ? action(source) : defaultValue; } /// <summary> Проталкивает значение дальше, если выполняется условие, в противном случае возвращает значение типа по умолчанию </summary> public static TSource? If<TSource>(this TSource? source, Func<TSource?, bool> condition) where TSource : struct { return source.HasValue && condition(source) ? source : default(TSource); } /// <summary> Пироталкивает значение дальше, если условие не выполняется, в противном случае возвращает значение по умолчанию </summary> public static TSource? IfNot<TSource>(this TSource? source, Func<TSource?, bool> condition) where TSource : struct { return source.HasValue && !condition(source) ? source : default(TSource); } /// <summary> Если объект не существует, восстанавливает его указанным способом </summary> public static TInput Recover<TInput>(this TInput? source, Func<TInput> recoverFunc) where TInput : struct { return source.HasValue ? source.Value : recoverFunc(); } /// <summary> Возвращает true если объект не существует </summary> public static bool IsNull<TSource>(this TSource? source) where TSource : struct { return source.HasValue == false; } /// <summary> Возвращает true если объект существует </summary> public static bool IsNotNull<TSource>(this TSource? source) where TSource : struct { return source.HasValue; } } public static class MaybeObjects { /// <summary> Выполняет действие, если объект существует </summary> public static TSource Do<TSource>(this TSource source, Action<TSource> action) where TSource : class { if (checkNotNull(source)) action(source); return source; } /// <summary> Выполняет действие, если объект существует </summary> public static TSource DoNull<TSource>(this TSource source, Action action) where TSource : class { if (checkNull(source)) action(); return source; } /// <summary> Проталкивает значение, если объект существует </summary> public static TResult With<TSource, TResult>(this TSource source, Func<TSource, TResult> action) where TSource : class { return checkNotNull(source) ? action(source) : default(TResult); } /// <summary> Проталкивает значение, если объект существует, иначе возвращает наше значение по умолчанию </summary> public static TResult Return<TSource, TResult>(this TSource source, Func<TSource, TResult> action, TResult defaultValue) where TSource : class { return checkNotNull(source) ? action(source) : defaultValue; } /// <summary> Проталкивает значение, если объект существует, иначе возвращает наше значение по умолчанию </summary> public static bool ReturnSuccess<TSource>(this TSource source) where TSource : class { return checkNotNull(source); } /// <summary> Проталкивает значение дальше, если выполняется условие </summary> public static TSource If<TSource>(this TSource source, Func<TSource, bool> condition) where TSource : class { return checkNotNull(source) && condition(source) ? source : default(TSource); } /// <summary> Проталкивает значение дальше, если условие не выполняется</summary> public static TSource IfNot<TSource>(this TSource source, Func<TSource, bool> condition) where TSource : class { return checkNotNull(source) && !condition(source) ? source : default(TSource); } /// <summary> Восстанавливает объект указанным способом если он не существует </summary> public static TInput Recover<TInput>(this TInput source, Func<TInput> action) where TInput : class { return source ?? action(); } /// <summary> Восстанавливает объект указанным способом если он не существует, и удаляет, если не существует </summary> public static TInput Else<TInput>(this TInput source, Func<TInput> action) where TInput : class { return checkNotNull(source) ? null : action(); } /// <summary> Преобразует объект в указанный тип </summary> public static TResult OfType<TResult>(this object source) { return source is TResult ? (TResult)source : default(TResult); } public static TInput Throw<TInput>(this TInput source) where TInput : class { if (checkNull(source)) throw new NullReferenceException(string.Format("Source of type {0} can not be null", typeof(TInput))); return source; } public static TInput Throw<TInput>(this TInput source, string nullExceptionText) where TInput : class { if (checkNull(source)) throw new NullReferenceException(nullExceptionText); return source; } public static TInput Throw<TInput>(this TInput source, params string[] nullExceptionTexts) where TInput : class { if (checkNull(source)) throw new NullReferenceException(nullExceptionTexts != null ? string.Join(Environment.NewLine, nullExceptionTexts) : string.Format("Source of type {0} can not be null", typeof(TInput))); return source; } /// <summary> Возвращает true если объект не существует </summary> public static bool IsNull<TSource>(this TSource source) where TSource : class { return checkNull(source); } /// <summary> Возвращает true если объект существует </summary> public static bool IsNotNull<TSource>(this TSource source) where TSource : class { return checkNotNull(source); } public static T ChangeIf<T>(this T o, Predicate<T> predicate, Func<T, T> func) { if (predicate(o)) return func(o); return o; } //Из за бага UnityEngine.Object с проверкой на null проверять нужно через эти функции private static bool checkNull(object a) { return a == null || a.Equals(null); } private static bool checkNotNull(object a) { return !checkNull(a); } } }
Смотрите также:
Комментарии
Здесь еще никто не оставил комментарий
CollectableItemData.cs
[CreateMenuItem(fileName = "newItem", menuName = "Data/Items/Collectable", order = 51]