我最近正在使用一个DateTime对象,并写了这样的东西:

DateTime dt = DateTime.Now;
dt.AddDays(1);
return dt; // still today's date! WTF?

AddDays()的智能感知文档说它在日期后添加了一天,但它并没有这样做——它实际上返回了一个添加了一天的日期,所以你必须这样写:

DateTime dt = DateTime.Now;
dt = dt.AddDays(1);
return dt; // tomorrow's date

这个问题以前已经困扰过我很多次了,所以我认为将最糟糕的c#陷阱分类会很有用。


当前回答

递归属性有问题

我认为不是c#特有的,而且我确信我在SO的其他地方看到过它(这个问题让我想起了它)

它有两种发生方式,但最终结果是一样的:

忘记引用基数。当重写一个属性时:

 public override bool IsRecursive
 {
     get { return IsRecursive; }
     set { IsRecursive = value; }
 }

从auto-属性改为back -属性,但并没有完全改变:

public bool IsRecursive
{
    get { return IsRecursive; }
    set { IsRecursive = value; }
}

其他回答

合同在流。阅读是我见过很多人被绊倒的东西:

// Read 8 bytes and turn them into a ulong
byte[] data = new byte[8];
stream.Read(data, 0, 8); // <-- WRONG!
ulong data = BitConverter.ToUInt64(data);

这是错误的原因是流。Read最多读取指定的字节数,但完全可以只读取1个字节,即使在流结束前还有7个字节可用。

它看起来与Stream如此相似,这并没有什么帮助。如果没有异常返回,则保证已写入所有字节。上面的代码几乎一直都能工作,这也没有什么帮助。当然,没有现成的、方便的方法来正确地读取N个字节也无济于事。

所以,为了堵住这个漏洞,提高人们的意识,这里有一个正确的方法:

    /// <summary>
    /// Attempts to fill the buffer with the specified number of bytes from the
    /// stream. If there are fewer bytes left in the stream than requested then
    /// all available bytes will be read into the buffer.
    /// </summary>
    /// <param name="stream">Stream to read from.</param>
    /// <param name="buffer">Buffer to write the bytes to.</param>
    /// <param name="offset">Offset at which to write the first byte read from
    ///                      the stream.</param>
    /// <param name="length">Number of bytes to read from the stream.</param>
    /// <returns>Number of bytes read from the stream into buffer. This may be
    ///          less than requested, but only if the stream ended before the
    ///          required number of bytes were read.</returns>
    public static int FillBuffer(this Stream stream,
                                 byte[] buffer, int offset, int length)
    {
        int totalRead = 0;
        while (length > 0)
        {
            var read = stream.Read(buffer, offset, length);
            if (read == 0)
                return totalRead;
            offset += read;
            length -= read;
            totalRead += read;
        }
        return totalRead;
    }

    /// <summary>
    /// Attempts to read the specified number of bytes from the stream. If
    /// there are fewer bytes left before the end of the stream, a shorter
    /// (possibly empty) array is returned.
    /// </summary>
    /// <param name="stream">Stream to read from.</param>
    /// <param name="length">Number of bytes to read from the stream.</param>
    public static byte[] Read(this Stream stream, int length)
    {
        byte[] buf = new byte[length];
        int read = stream.FillBuffer(buf, 0, length);
        if (read < length)
            Array.Resize(ref buf, read);
        return buf;
    }

Oracle参数必须按顺序添加

这是ODP . net实现Oracle参数化查询的一个主要问题。

在向查询中添加参数时,默认行为是忽略参数名,并按添加值的顺序使用值。

解决方案是将OracleCommand对象的BindByName属性设置为true -默认为false…这是定性的(如果不是定量的),就像有一个属性叫做DropDatabaseOnQueryExecution,默认值为true。

他们称之为特征;我称之为公共领域的坑。

请看这里了解更多细节。

重载==操作符和非类型化容器(数组列表、数据集等):

string my = "my ";
Debug.Assert(my+"string" == "my string"); //true

var a = new ArrayList();
a.Add(my+"string");
a.Add("my string");

// uses ==(object) instead of ==(string)
Debug.Assert(a[1] == "my string"); // true, due to interning magic
Debug.Assert(a[0] == "my string"); // false

解决方案?

总是使用字符串。当比较字符串类型时等于(a, b) 使用像List<string>这样的泛型来确保两个操作数都是字符串。

如果你正在为MOSS编写代码,你以这种方式获得一个站点引用:

SPSite oSiteCollection = SPContext.Current.Site;

之后在你的代码中你说:

oSiteCollection.Dispose();

从MSDN:

If you create an SPSite object, you can use the Dispose method to close the object. However, if you have a reference to a shared resource, such as when the object is provided by the GetContextSite method or Site property (for example, SPContext.Current.Site), do not use the Dispose method to close the object, but instead allow Windows SharePoint Services or your portal application to manage the object. For more information about object disposal, see Best Practices: Using Disposable Windows SharePoint Services Objects.

每个MOSS程序员都会遇到这种情况。

TextInfo textInfo = Thread.CurrentThread.CurrentCulture.TextInfo;

textInfo.ToTitleCase("hello world!"); //Returns "Hello World!"
textInfo.ToTitleCase("hElLo WoRld!"); //Returns "Hello World!"
textInfo.ToTitleCase("Hello World!"); //Returns "Hello World!"
textInfo.ToTitleCase("HELLO WORLD!"); //Returns "HELLO WORLD!"

是的,这种行为是有记录的,但这并不能证明它是正确的。