2010-08-21 18 views
5

un código simple:Banderas de bits: ¿Qué me estoy perdiendo?

protected void Page_Load(object sender, EventArgs e) 
{ 
    DateTime now = DateTime.UtcNow; 

    lit.Text += "<br/>now.DayOfWeek: " + now.DayOfWeek.ToString(); 

    // weekdays (Saturday is not included) 
    DayOfWeek runningDays = DayOfWeek.Monday | DayOfWeek.Tuesday | DayOfWeek.Wednesday | DayOfWeek.Thursday | DayOfWeek.Friday; 

    lit.Text += "<br/>" + runningDays.HasFlag(now.DayOfWeek); 
    lit.Text += "<br/>" + runningDays.HasAny(now.DayOfWeek); 
    lit.Text += "<br/>" + ((runningDays & now.DayOfWeek) != 0); 

    // weekend (Saturday is in a weekend) 
    runningDays = DayOfWeek.Saturday | DayOfWeek.Sunday; 

    lit.Text += "<br/>" + runningDays.HasFlag(now.DayOfWeek); 
    lit.Text += "<br/>" + runningDays.HasAny(now.DayOfWeek); 
    lit.Text += "<br/>" + ((runningDays & now.DayOfWeek) != 0); 
} 

Un ayudante:

public static bool HasExactly(this DayOfWeek x, DayOfWeek y) { return x == y; } 
public static bool HasAny(this DayOfWeek x, DayOfWeek y) { return 0 != (x & y); } 
public static bool HasAll(this DayOfWeek x, DayOfWeek y) { return y == (x & y); } 

de salida de hoy (Sábado)

now.DayOfWeek: Saturday 
True 
True 
True 
True 
True 
True 

embargo, la salida debería ser como:

now.DayOfWeek: Saturday 
False 
False 
False 
True 
True 
True 

Wh ¿Me estoy perdiendo aquí?

Respuesta

11

Los días de la semana no son indicadores de bits. http://msdn.microsoft.com/en-us/library/system.datetime.dayofweek.aspx

El valor de las constantes en la enumeración DayOfWeek varía de DayOfWeek.Sunday a DayOfWeek.Saturday. Si se envía a un número entero , su valor va desde cero (que indica DayOfWeek.Sunday) a six (que indica DayOfWeek.Saturday).

+0

0 (domingo) a 6 (sábado). – sisve

+0

Sabía que había sido estúpido :(Gracias por indicarme los documentos ... Sigo olvidando que son una parte importante del rol de desarrollador ... pero realmente asumí que DayOfWeek era un Flag Enum: o ( – balexandre

1

DayOfWeek tiene números secuenciales.

Utilice un List<DayOfWeek>.

Ir a definición muestra:

// Summary: 
//  Specifies the day of the week. 
[Serializable] 
[ComVisible(true)] 
public enum DayOfWeek 
{ 
    // Summary: 
    //  Indicates Sunday. 
    Sunday = 0, 
    // 
    // Summary: 
    //  Indicates Monday. 
    Monday = 1, 
    // 
    // Summary: 
    //  Indicates Tuesday. 
    Tuesday = 2, 
    // 
    // Summary: 
    //  Indicates Wednesday. 
    Wednesday = 3, 
    // 
    // Summary: 
    //  Indicates Thursday. 
    Thursday = 4, 
    // 
    // Summary: 
    //  Indicates Friday. 
    Friday = 5, 
    // 
    // Summary: 
    //  Indicates Saturday. 
    Saturday = 6, 
} 
+0

err ... entonces no puede aplicar operadores de bits donde en este ejemplo son los mejores para ser utilizados! – balexandre

+0

No. Pero lo mejor puede ser desde un punto de vista de rendimiento de optimización prematura, no punto de vista de legibilidad. Lista.Contiene, etc. son más fáciles de leer. –

2

Usted puede crear su propia enumeración DayOfWeek si hay que usarla como banderas:

[Flags] 
public enum MyDayOfWeek { Sunday = 1, Monday = 2, Tuesday = 4, ... , Saturday = 64 }; 
+0

sí, terminé haciendo eso :) pero asumí equivocadamente que DayOfWeek era un Enumerador de Bandera ... Gracias. – balexandre

0

La enumeración DayOfWeek fue diseñado para representar un solo día de la semana, no un conjunto de días.

No obtiene un error de compilación para usar & porque las enumeraciones son números enteros, pero el operador no hace lo que espera (a menos que solo programe eventos los lunes, martes o jueves).

Si desea un indicador de bit, entonces declare un tipo de indicador de bit, como sugiere Ray.

+0

sí ... mi error fue suponer que DayofWeek era un tipo de bandera. .. nunca me ocurre de otra manera ... tonto :-( – balexandre

5

Sé que esto es una entrada antigua, pero por si acaso - una sintaxis ordenada para hacer banderas enumeraciones es

[Flags] 
public enum DaysOfWeek 
{ 
    None = 1 << 0, 
    Monday = 1 << 1, 
    Tuesday = 1 << 2, 
    Wednesday = 1 << 3, 
    Thursday = 1 << 4, 
    Friday = 1 << 5, 
    Saturday = 1 << 6, 
    Sunday = 1 << 7 
} 

Se necesitaría Ninguno para indicar nada fue seleccionado. Tal enumeración le permite indicar varios días, por ejemplo:

var selectedDays = DaysOfWeek.Tuesday | DaysOfWeek.Friday; 

Sin comentarios es de esperar sea necesario. Y con el fin de "decodificar" el valor:

public bool IsDayOfWeekSelected(DaysOfWeek which, DaysOfWeek selection) 
{ 
    return selection & which == which; 
} 

y esto entonces nos permite llamar a:

var isTuesday = IsDayOfWeekSelected(DaysOfWeek.Tuesday, selectedDays); // => true 
var isWednesday = IsDayOfWeekSelected(DaysOfWeek.Wednesday, selectedDays); // => false 
var isFriday = IsDayOfWeekSelected(DaysOfWeek.Friday, selectedDays); // => true 

Espero que esto ayude a alguien.

+1

Me gustaría ir con el Método de Extensión, algo así como: 'public static bool IsDayOfWeekSelected (DaysOfWeek selectedDays, DaysOfWeek which) {return selection & wh ich == que; } 'entonces simplemente podría hacer:' selectedDays.IsDayOfWeekSelected (DaysOfWeek.Tuesday); '; o) – balexandre

+0

Buen punto. Ellos no tienen que rellenarlo en una clase de Utilidad :) –

+0

Siempre dejaría 'None' en 0, y también puede usar' Sunday = 1 << DayOfWeek.Sunday' etc para mapear a .NET ' DayOfWeek' –

Cuestiones relacionadas