Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

ความแตกต่างระหว่าง | และ || (OR Operators) ใน C#

ใน C# มี OR Operator 2 แบบ ที่ทำงานต่างกันในระดับ Bitwise และ Logical

1. | - Bitwise OR / Logical OR (Non-Short-circuiting)

  • Bitwise: บน Integer Types (int, long, byte...) ทำ OR ทีละ Bit
  • Logical: บน bool ประเมิน ทั้งสอง Operand เสมอ (Non-Short-circuiting)

Bitwise Example

int a = 4;  // Binary: 0100
int b = 3;  // Binary: 0011
int c = a | b; // 0111 = 7
Console.WriteLine(c); // 7

Logical Example (Non-Short-circuiting)

bool GetTrue()
{
    Console.WriteLine("GetTrue called");
    return true;
}

bool GetFalse()
{
    Console.WriteLine("GetFalse called");
    return false;
}

static void Main()
{
    // | ประเมิน ทั้งคู่เสมอ
    bool result = GetTrue() | GetFalse(); 
    // Output:
    // GetTrue called
    // GetFalse called
    // result = true
}

2. || - Conditional Logical OR (Short-circuiting)

  • ทำงานกับ bool เท่านั้น
  • Short-circuit: หาก Operand แรกเป็น true → ไม่ประเมิน Operand ที่สอง
  • เร็วกว่า และปลอดภัยกว่า (Null Check, Expensive Call)

Example

static void Main()
{
    // || Short-circuits
    bool result = GetTrue() || GetFalse(); 
    // Output:
    // GetTrue called
    // result = true (GetFalse ไม่ถูกเรียก!)
    
    // Practical: Null Check
    string str = null;
    if (str != null || str.Length > 0) // Safe: str.Length ไม่ถูกเรียกถ้า str == null
        Console.WriteLine("Not empty");
}

ตารางเปรียบเทียบ

Feature | (Bitwise/Logical) || (Conditional)
Operand Types Integral, Enum, bool, Nullable<bool> bool, Nullable<bool> เท่านั้น
Evaluation Always Both (Eager) Short-circuit (Lazy)
Performance Slower (Always Eval Both) Faster (May Skip Second)
Side Effects Both Executed Second May Be Skipped
Use Case Bit Flags, Enum Flags, Must Eval Both General Boolean Logic, Null Guards

Enum Flags (Bitwise |)

[Flags]
public enum FileAccess
{
    None = 0,
    Read = 1,      // 0001
    Write = 2,     // 0010
    Execute = 4,   // 0100
    Delete = 8     // 1000
}

FileAccess access = FileAccess.Read | FileAccess.Write; // 0011 = 3 (Read + Write)
bool canWrite = (access & FileAccess.Write) == FileAccess.Write; // Check Flag

Console.WriteLine(access); // "Read, Write" (ToString() รองรับ Flags)

Nullable (bool?)

bool? a = true;
bool? b = null;
bool? c = false;

Console.WriteLine(a | b);  // true  (true | anything = true)
Console.WriteLine(b | c);  // null  (null | false = null)
Console.WriteLine(b | a);  // true  (null | true = true)

Console.WriteLine(a || b); // true  (Short-circuit: a=true -> stop)
Console.WriteLine(c || b); // null  (c=false -> eval b=null -> null)
// Note: || กับ nullable ต้องการ lifted operator

Best Practice

  • ใช้ || สำหรับ Boolean Logic ทั่วไป (Performance, Safety)
  • ใช้ | สำหรับ Bitwise Operations (Flags, Bit Masks)
  • ใช้ | กับ Boolean กรณี ต้องการให้ Side Effects ทั้งคู่ทำงาน (Rare)
  • & และ && มีความสัมพันธ์เหมือนกัน (AND)