SORU
16 Temmuz 2010, Cuma


C içinde bir bit maskesi kullanarak#

Şu var ki

int susan = 2; //0010
int bob = 4; //0100
int karen = 8; //1000

ve bir yöntem için parametre olarak 10 (8 2) geçer ve bu susan ve karen demek için çözmek istiyorum

10 1010 olduğunu biliyorum

ama nasıl bir mantık eğer belirli bir bit olarak işaretli olup olmadığını görmek için ne yapabilirim

if (condition_for_karen) // How to quickly check whether effective karen bit is 1

Şu an aklıma gelen bütün geçtim numarası olup olmadığını kontrol edin

14 // 1110
12 // 1100
10 // 1010
8 //  1000

Ben daha büyük bir sayı gerçek bit benim gerçek dünya senaryo, bu gibi pratik, ne daha iyi bir yolu kullanarak bir maske için sadece onay olsa da olmasa da ben karşılamak koşulu için sadece karen?

Sonra sağa sonra tekrar bit ilgileniyorum dışındaki temizlemek için değişen sol vites düşünemiyorum, ama bu da aşırı karmaşık görünüyor.

CEVAP
16 Temmuz 2010, Cuma


Bunu yapmak için geleneksel yolu enum: Flags niteliğini kullanmaktır

[Flags]
public enum Names
{
    None = 0,
    Susan = 1,
    Bob = 2,
    Karen = 4
}

Sonra aşağıdaki gibi belirli bir ad için kontrol ediyorum

Names names = Names.Susan | Names.Bob;

// evaluates to true
bool susanIsIncluded = (names & Names.Susan) != Names.None;

// evaluates to false
bool karenIsIncluded = (names & Names.Karen) != Names.None;

Mantıksal bit kombinasyonları hatırlamak zor olabilir, kendime hayat daha kolay FlagsHelper a sınıfı* ile yaptım.:

// The casts to object in the below code are an unfortunate necessity due to
// C#'s restriction against a where T : Enum constraint. (There are ways around
// this, but they're outside the scope of this simple illustration.)
public static class FlagsHelper
{
    public static bool IsSet<T>(T flags, T flag) where T : struct
    {
        int flagsValue = (int)(object)flags;
        int flagValue = (int)(object)flag;

        return (flagsValue & flagValue) != 0;
    }

    public static void Set<T>(ref T flags, T flag) where T : struct
    {
        int flagsValue = (int)(object)flags;
        int flagValue = (int)(object)flag;

        flags = (T)(object)(flagsValue | flagValue);
    }

    public static void Unset<T>(ref T flags, T flag) where T : struct
    {
        int flagsValue = (int)(object)flags;
        int flagValue = (int)(object)flag;

        flags = (T)(object)(flagsValue & (~flagValue));
    }
}

Bu bana yukarıdaki kod olarak: yeniden yazmak için izin verecek

Names names = Names.Susan | Names.Bob;

bool susanIsIncluded = FlagsHelper.IsSet(names, Names.Susan);

bool karenIsIncluded = FlagsHelper.IsSet(names, Names.Karen);

Ayrıca bunu yaparak: ayarlamak için Karen ekleyebilirim unutmayın

FlagsHelper.Set(ref names, Names.Karen);

Ve benzer bir şekilde Susan çıkarabilirim:

FlagsHelper.Unset(ref names, Names.Susan);

Porges *işaret, zaten var yukarıda IsSet yönteminin eşdeğer .NET 4.0: Enum.HasFlag. Set Unset yöntemleri benzerleri var ama görünmüyor; ama bu sınıftaki bazı hak etti diyebilirim.


Not: Kullanarak çeteleler sadecegelenekselbu sorunu çözmede yol. Tamamen yukarıdaki kod tüm in yerine kullanmak çevirebilir ve sadece aynı işi görür.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Charles Renaud

    Charles Rena

    10 Kasım 2007
  • EminemVEVO

    EminemVEVO

    12 Mayıs 2009
  • RickardRick

    RickardRick

    9 Mart 2007