C# 或 .NET 中最糟糕的问题是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/241134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:26:14  来源:igfitidea点击:

What is the worst gotcha in C# or .NET?

c#.net

提问by MusiGenesis

I was recently working with a DateTimeobject, and wrote something like this:

我最近在处理一个DateTime对象,并写了这样的东西:

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

The intellisense documentation for AddDays()says it adds a day to the date, which it doesn't - it actually returnsa date with a day added to it, so you have to write it like:

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

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

This one has bitten me a number of times before, so I thought it would be useful to catalog the worst C# gotchas.

这个问题之前已经让我咬了很多次,所以我认为列出最糟糕的 C# 问题会很有用。

采纳答案by Eric Z Beard

private int myVar;
public int MyVar
{
    get { return MyVar; }
}

Blammo. Your app crashes with no stack trace. Happens all the time.

布拉莫。您的应用程序在没有堆栈跟踪的情况下崩溃。无时无刻不在发生。

(Notice capital MyVarinstead of lowercase myVarin the getter.)

(注意getter 中的大写MyVar而不是小写myVar。)

回答by Mitchel Sellers

I saw this one posted the other day, and I think it is pretty obscure, and painful for those that don't know

我前几天看到这个贴,我觉得它很晦涩,对于不知道的人来说很痛苦

int x = 0;
x = x++;
return x;

As that will return 0 and not 1 as most would expect

因为这将返回 0 而不是大多数人所期望的 1

回答by tvanfosson

mystring.Replace("x","y")

While it looks like it should do the replacement on the string it's being invoked on it actually returns a new string with the replacements made without changing the string it's invoked on. You need to remember that strings are immutable.

虽然它看起来应该对它正在调用的字符串进行替换,但实际上返回一个新字符串,并在不更改它被调用的字符串的情况下进行替换。您需要记住字符串是不可变的。

回答by Jon Skeet

Type.GetType

类型.GetType

The one which I've seen bite lots of people is Type.GetType(string). They wonder why it works for types in their own assembly, and some types like System.String, but not System.Windows.Forms.Form. The answer is that it only looks in the current assembly and in mscorlib.

我见过咬了很多人的那个是Type.GetType(string)。他们想知道为什么它适用于他们自己的程序集中的类型,而某些类型如System.String,但不适用于System.Windows.Forms.Form. 答案是它只在当前程序集和mscorlib.



Anonymous methods

匿名方法

C# 2.0 introduced anonymous methods, leading to nasty situations like this:

C# 2.0 引入了匿名方法,导致了如下令人讨厌的情况:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            ThreadStart ts = delegate { Console.WriteLine(i); };
            new Thread(ts).Start();
        }
    }
}

What will that print out? Well, it entirely depends on the scheduling. It will print 10 numbers, but it probably won't print 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 which is what you might expect. The problem is that it's the ivariable which has been captured, not its value at the point of the creation of the delegate. This can be solved easily with an extra local variable of the right scope:

那会打印出什么?嗯,这完全取决于日程安排。它将打印 10 个数字,但它可能不会打印 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 这正是您所期望的。问题在于它是i被捕获的变量,而不是它在创建委托时的值。这可以通过正确范围的额外局部变量轻松解决:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            int copy = i;
            ThreadStart ts = delegate { Console.WriteLine(copy); };
            new Thread(ts).Start();
        }
    }
}


Deferred execution of iterator blocks

迭代器块的延迟执行

This "poor man's unit test" doesn't pass - why not?

这个“穷人的单元测试”没有通过——为什么不通过?

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Test
{
    static IEnumerable<char> CapitalLetters(string input)
    {
        if (input == null)
        {
            throw new ArgumentNullException(input);
        }
        foreach (char c in input)
        {
            yield return char.ToUpper(c);
        }
    }

    static void Main()
    {
        // Test that null input is handled correctly
        try
        {
            CapitalLetters(null);
            Console.WriteLine("An exception should have been thrown!");
        }
        catch (ArgumentNullException)
        {
            // Expected
        }
    }
}

The answer is that the code within the source of the CapitalLetterscode doesn't get executed until the iterator's MoveNext()method is first called.

答案是,在第一次调用CapitalLetters迭代器的MoveNext()方法之前,不会执行代码源中的代码。

I've got some other oddities on my brainteasers page.

我的脑筋急转弯页面上还有其他一些奇怪的东西。

回答by Jimmy

overloaded == operators and untyped containers (arraylists, datasets, etc.):

重载 == 运算符和无类型容器(数组列表、数据集等):

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

Solutions?

解决方案?

  • always use string.Equals(a, b)when you are comparing string types

  • using generics like List<string>to ensure that both operands are strings.

  • string.Equals(a, b)比较字符串类型时总是使用

  • 使用泛型List<string>来确保两个操作数都是字符串。

回答by Jon B

Here's another time one that gets me:

这是另一个让我着迷的时间:

static void PrintHowLong(DateTime a, DateTime b)
{
    TimeSpan span = a - b;
    Console.WriteLine(span.Seconds);        // WRONG!
    Console.WriteLine(span.TotalSeconds);   // RIGHT!
}


TimeSpan.Secondsis the seconds portion of the timespan (2 minutes and 0 seconds has a seconds value of 0).

TimeSpan.Seconds是时间跨度的秒部分(2 分 0 秒的秒值为 0)。

TimeSpan.TotalSecondsis the entire timespan measured in seconds (2 minutes has a total seconds value of 120).

TimeSpan.TotalSeconds是以秒为单位测量的整个时间跨度(2 分钟的总秒值为 120)。

回答by Jeff Kotula

Garbage collection and Dispose(). Although you don't have to do anything to free up memory, you still have to free up resourcesvia Dispose(). This is an immensely easy thing to forget when you are using WinForms, or tracking objects in any way.

垃圾收集和 Dispose()。虽然您不必做任何事情来释放内存,但您仍然需要通过 Dispose()来释放资源。当您使用 WinForms 或以任何方式跟踪对象时,这是一件非常容易忘记的事情。

回答by Jeff Kotula

Some code:

一些代码:

        List<int> a = new List<int>();
        for (int i = 0; i < 10; i++)
        {
            a.Add(i);
        }

        var q1 = (from aa in a
                  where aa == 2
                  select aa).Single();

        var q2 = (from aa in a
                  where aa == 2
                  select aa).First();

q1 - in this query check all integers in List; q2 - check integers until find "right" integer.

q1 - 在这个查询中检查 List 中的所有整数;q2 - 检查整数直到找到“正确”的整数。

回答by cciotti

If you're coding for MOSS and you get a site reference this way:

如果您正在为 MOSS 编码并通过以下方式获得站点参考:

SPSite oSiteCollection = SPContext.Current.Site;

and later in your code you say:

后来在你的代码中你说:

oSiteCollection.Dispose();

From MSDN:

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.
如果创建 SPSite 对象,则可以使用 Dispose 方法关闭该对象。但是,如果您有对共享资源的引用,例如当对象由 GetContextSite 方法或 Site 属性(例如 SPContext.Current.Site)提供时,请不要使用 Dispose 方法关闭对象,而是使用允许 Windows SharePoint Services 或您的门户应用程序管理对象。有关对象处置的详细信息,请参阅最佳实践:使用一次性 Windows SharePoint Services 对象。

This happens to every MOSS programmer and some point.

这发生在每个 MOSS 程序员身上,在某些时候。

回答by user25306

When you start a process (using System.Diagnostics) that writes to the console, but you never read the Console.Out stream, after a certain amount of output your app will appear to hang.

当您启动一个写入控制台的进程(使用 System.Diagnostics),但您从未读取 Console.Out 流时,在一定量的输出后,您的应用程序似乎会挂起。