Я начал работать с C# несколько недель назад, и я нахожусь теперь в ситуации, где я должен создать флаг "набора битов" для обработки различных случаев в алгоритме. У меня есть таким образом две опции:
enum RelativePositioning
{
LEFT = 0,
RIGHT = 1,
BOTTOM = 2,
TOP = 3,
FRONT = 4,
BACK = 5
}
pos = ((eye.X < minCorner.X ? 1 : 0) << (int) RelativePositioning.LEFT)
+ ((eye.X > maxCorner.X ? 1 : 0) << (int) RelativePositioning.RIGHT)
+ ((eye.Y < minCorner.Y ? 1 : 0) << (int) RelativePositioning.BOTTOM)
+ ((eye.Y > maxCorner.Y ? 1 : 0) << (int) RelativePositioning.TOP)
+ ((eye.Z < minCorner.Z ? 1 : 0) << (int) RelativePositioning.FRONT)
+ ((eye.Z > maxCorner.Z ? 1 : 0) << (int) RelativePositioning.BACK);
Или:
enum RelativePositioning
{
LEFT = 1,
RIGHT = 2,
BOTTOM = 4,
TOP = 8,
FRONT = 16,
BACK = 32
}
if (eye.X < minCorner.X) { pos += (int) RelativePositioning.LEFT; }
if (eye.X > maxCorner.X) { pos += (int) RelativePositioning.RIGHT; }
if (eye.Y < minCorner.Y) { pos += (int) RelativePositioning.BOTTOM; }
if (eye.Y > maxCorner.Y) { pos += (int) RelativePositioning.TOP; }
if (eye.Z > maxCorner.Z) { pos += (int) RelativePositioning.FRONT; }
if (eye.Z < minCorner.Z) { pos += (int) RelativePositioning.BACK; }
Я, возможно, использовал что-то как ((eye.X > maxCorner.X) << 1)
но C# не позволяет неявный кастинг от bool до интервала, и тернарный оператор был достаточно подобен. Мой вопрос теперь: есть ли какое-либо повышение производительности в использовании первой версии по второму?
Спасибо
Tommaso
Оператор inline if
(?
, :
) сгенерирует почти такой же IL, как и стандартный список if
во втором примере. Единственное различие, которое вы увидите здесь, это конкретные операции, которые будет выполнять процессор, и я могу поспорить, что ADD
будет быстрее, чем SHL
.
Поскольку вы все равно будете складывать результаты, я бы выбрал второй пример (к тому же он гораздо легче читается).
EDIT
Я только что проверил IL обоих примеров, и это противоречит тому, что я сказал выше.
Первый пример генерирует гораздо меньше IL (на 34 строки меньше), поэтому вам придется провести тест производительности, чтобы определить, быстрее ли он.
Вы обязательно должны использовать атрибут Flags для своего перечисления. Таким образом, это будет выглядеть примерно так:
[Flags]
public enum RelativePositionings
{
None = 0,
Left = 1,
Right = 2,
Bottom = 4,
Top = 8,
Front = 16,
Back = 32
}
С его помощью вы можете делать такие вещи, как:
var position = RelativePositionings.Left | RelativePositionings.Front;
и проверять каждое состояние:
if(position.HasFlag(RelativePositioning.Left))
{
//To do: if left bit is set?
}