В Подрывной деятельности (и CVS), репозиторий прежде всего. В мерзавце и подвижный нет действительно понятия репозитория таким же образом; здесь изменения являются центральной темой.
я не думал очень о том, как Вы реализовали бы любого, но мое впечатление (на основе горького опыта и большого чтения) - то, что это различие - то, что делает слияние и ветвление настолько легче в находящихся в нерепозитории системах.
РЕДАКТИРОВАТЬ: Теперь доступна библиотека, поддерживающая это через ildasm / ilasm: UnconstrainedMelody .
Члены команды C # ранее заявляли, что хотели бы иметь возможность поддерживать где T: Enum
и , где T: Delegate
, но это никогда не было достаточно высоким приоритетом. (Я не уверен, в чем причина наличия ограничения, по общему признанию ...)
Наиболее практичный обходной путь в C #:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
// ...
}
Это теряет проверку во время компиляции для "enum-ness" "но проверяет, что вы используете один и тот же тип в обоих местах. Конечно, у него также есть штраф времени выполнения проверки. Вы можете избежать этого штрафа во время выполнения после первого вызова, используя общий вложенный тип для реализации, которая генерирует исключение в статическом конструкторе:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
return EnumHelper<T>.HasFlags(value, flags);
}
private class EnumHelper<T> where T : struct
{
static EnumHelper()
{
if (!typeof(Enum).IsAssignableFrom(typeof(T))
{
throw new InvalidOperationException(); // Or something similar
}
}
internal static HasFlags(T value, T flags)
{
...
}
}
Как упоминает Греко, вы можете написать метод на C ++ / CLI, а затем ссылаться на библиотека классов из C # в качестве другого варианта.
Я не уверен, в чем причина наличия ограничения, по общему признанию ...)Наиболее практичный обходной путь в C #:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
// ...
}
Это теряет проверку времени компиляции для "перечисления", но сохраняет проверка того, что вы используете один и тот же тип в обоих местах. Конечно, у него также есть штраф времени выполнения проверки. Вы можете избежать этого штрафа во время выполнения после первого вызова, используя общий вложенный тип для реализации, которая генерирует исключение в статическом конструкторе:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
return EnumHelper<T>.HasFlags(value, flags);
}
private class EnumHelper<T> where T : struct
{
static EnumHelper()
{
if (!typeof(Enum).IsAssignableFrom(typeof(T))
{
throw new InvalidOperationException(); // Or something similar
}
}
internal static HasFlags(T value, T flags)
{
...
}
}
Как упоминает Греко, вы можете написать метод на C ++ / CLI, а затем ссылаться на библиотека классов из C # в качестве другого варианта.
Я не уверен, в чем причина наличия ограничения, по общему признанию ...)Наиболее практичный обходной путь в C #:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
// ...
}
Это теряет проверку времени компиляции для "перечисления", но сохраняет проверка того, что вы используете один и тот же тип в обоих местах. Конечно, у него также есть штраф времени выполнения проверки. Вы можете избежать этого штрафа во время выполнения после первого вызова, используя общий вложенный тип для реализации, которая генерирует исключение в статическом конструкторе:
public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
return EnumHelper<T>.HasFlags(value, flags);
}
private class EnumHelper<T> where T : struct
{
static EnumHelper()
{
if (!typeof(Enum).IsAssignableFrom(typeof(T))
{
throw new InvalidOperationException(); // Or something similar
}
}
internal static HasFlags(T value, T flags)
{
...
}
}
Как упоминает Греко, вы можете написать метод на C ++ / CLI, а затем ссылаться на библиотека классов из C # в качестве другого варианта.
но проверяет, что вы используете один и тот же тип в обоих местах. Конечно, у него также есть штраф времени выполнения проверки. Вы можете избежать этого штрафа во время выполнения после первого вызова, используя общий вложенный тип для реализации, которая генерирует исключение в статическом конструкторе:public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
return EnumHelper<T>.HasFlags(value, flags);
}
private class EnumHelper<T> where T : struct
{
static EnumHelper()
{
if (!typeof(Enum).IsAssignableFrom(typeof(T))
{
throw new InvalidOperationException(); // Or something similar
}
}
internal static HasFlags(T value, T flags)
{
...
}
}
Как упоминает Греко, вы можете написать метод на C ++ / CLI, а затем ссылаться на библиотека классов из C # в качестве другого варианта.
но проверяет, что вы используете один и тот же тип в обоих местах. Конечно, у него также есть штраф времени выполнения проверки. Вы можете избежать этого штрафа во время выполнения после первого вызова, используя общий вложенный тип для реализации, которая генерирует исключение в статическом конструкторе:public static bool HasFlags<T>(this T value, T flags) where T : struct
{
if (!(value is Enum))
{
throw new ArgumentException();
}
return EnumHelper<T>.HasFlags(value, flags);
}
private class EnumHelper<T> where T : struct
{
static EnumHelper()
{
if (!typeof(Enum).IsAssignableFrom(typeof(T))
{
throw new InvalidOperationException(); // Or something similar
}
}
internal static HasFlags(T value, T flags)
{
...
}
}
Как упоминает Греко, вы можете написать метод на C ++ / CLI, а затем ссылаться на библиотека классов из C # в качестве другого варианта.
На самом деле, возможно, с уродливой уловкой. Однако его нельзя использовать для методов расширения.
public abstract class Enums<Temp> where Temp : class {
public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
return (TEnum)Enum.Parse(typeof(TEnum), name);
}
}
public abstract class Enums : Enums<Enum> { }
Enums.Parse<DateTimeKind>("Local")
При желании вы можете предоставить Enums
частный конструктор и открытый вложенный абстрактный унаследованный класс с Temp
в качестве Enum
, чтобы предотвратить унаследованные версии для не перечислений.
Я не мог устоять перед попыткой обхода C ++, и, поскольку у меня все заработало, я решил поделиться им с остальными!
Вот код C ++ (мой C ++ очень ржавый, поэтому укажите на любые ошибки, в частности, в том, как определены аргументы):
#include "stdafx.h"
using namespace System;
using namespace System::Runtime::CompilerServices;
namespace Blixt
{
namespace Utilities
{
[Extension]
public ref class EnumUtility abstract sealed
{
public:
generic <typename T> where T : value class, Enum
[Extension]
static bool HasFlags(T value, T flags)
{
__int64 mask = Convert::ToInt64(flags);
return (Convert::ToInt64(value) & mask) == mask;
}
};
}
}
И код C # для тестирования (консольное приложение):
using System;
using Blixt.Utilities;
namespace Blixt.Playground
{
[Flags]
public enum Colors : byte
{
Black = 0,
Red = 1,
Green = 2,
Blue = 4
}
[Flags]
public enum Tastes : byte
{
Nothing = 0,
Sour = 1,
Sweet = 2,
Bitter = 4,
Salty = 8
}
class Program
{
static void Main(string[] args)
{
Colors c = Colors.Blue | Colors.Red;
Console.WriteLine("Green and blue? {0}", c.HasFlags(Colors.Green | Colors.Red));
Console.WriteLine("Blue? {0}", c.HasFlags(Colors.Blue));
Console.WriteLine("Green? {0}", c.HasFlags(Colors.Green));
Console.WriteLine("Red and blue? {0}", c.HasFlags(Colors.Red | Colors.Blue));
// Compilation error:
//Console.WriteLine("Sour? {0}", c.HasFlags(Tastes.Sour));
Console.WriteLine("Press any key to exit...");
Console.ReadKey(true);
}
}
}