System.Collections.BitArray长度调整未收缩m_array的解决方案问询
I totally get your frustration here—System.Collections.BitArray's Length property has a tricky gotcha that trips up a lot of developers: setting it to a shorter value doesn't always shrink the underlying byte array (m_array). It only marks how many bits are considered "valid" for basic operations like Get/Set, but when you call CopyTo, it still dumps the entire underlying byte array into your target. That’s exactly why your BitArrayToLong method returns 15 instead of 7—even though the first 3 bits are correct, the rest of the 8-byte array still holds the original value of 15.
Why This Happens
BitArray is optimized for resizing performance: it only shrinks the underlying byte array if the new length requires fewer full bytes than the current array. For example, if you go from 10 bits (2 bytes) to 7 bits (1 byte), it will shrink. But if you go from 64 bits (8 bytes) to 3 bits (still needs 1 byte), it leaves the 8-byte array intact—since the required byte count doesn’t drop below the current array’s size, it skips the shrink operation to avoid unnecessary memory reallocations.
Solution: Manually Truncate/Copy Bits
Since you can’t rely on BitArray.Length to clean up the underlying array, you need to explicitly create a new BitArray that only includes the bits you care about. Here’s how to fix your conversion methods:
Fixed BitArrayFromLong
This method creates a new BitArray with exactly your target bit length, copying only the relevant bits from the original long’s bit representation:
private const int _lengthInBits = 3; // Replace with your dynamic length in production private BitArray BitArrayFromLong(long lng) { var originalBits = new BitArray(BitConverter.GetBytes(lng)); var truncatedBits = new BitArray(_lengthInBits); // Copy only the first _lengthInBits bits for (int i = 0; i < _lengthInBits; i++) { truncatedBits[i] = originalBits[i]; } return truncatedBits; }
Fixed BitArrayToLong
This method ensures we only process the valid bits, ignoring any leftover data in the underlying array:
private long BitArrayToLong(BitArray bitArray) { int effectiveBits = Math.Min(bitArray.Length, _lengthInBits); var byteArray = new byte[sizeof(long)]; var tempBits = new BitArray(effectiveBits); // Copy only the valid bits to a temporary BitArray for (int i = 0; i < effectiveBits; i++) { tempBits[i] = bitArray[i]; } // Now CopyTo will only write bytes relevant to the effective bits tempBits.CopyTo(byteArray, 0); return BitConverter.ToInt64(byteArray, 0); }
General Approach for Other Types
For unsigned integers, signed integers, floats, doubles, and strings, apply the same core logic:
- When converting a value to a BitArray: create a BitArray of your target length, then copy only the required bits from the value’s byte representation.
- When converting back from a BitArray: first extract only the valid bits into a temporary BitArray (matching your target length), then copy that to a byte array and convert back to the desired type.
This way, you avoid any unexpected leftover data in the underlying byte array, ensuring your conversions are accurate every time.
内容的提问来源于stack exchange,提问作者Shefeto

