这三种清除文本框的方法有什么区别?

我对以下三种清除文本框内容的方法感到有点困惑。 我正在使用WPF并发现All正在工作,但我无法找到差异。

有人可以用一些例子向我解释一下吗?

  • txtUserName.Clear();
  • txtUserName.Text = string.Empty;
  • txtUserName.Text = "";

Clear()方法不仅仅是从TextBox删除TextBox 。 它删除所有内容并重置文本选择和插入符号@ syned的答案很好地显示。

对于txtUserName.Text = ""; 例如,如果字符串池中尚不存在空string对象,则框架将创建一个空string对象,并将其设置为Text属性。 但是,如果已在应用程序中使用字符串"" ,则Framework将使用池中的此值。

对于txtUserName.Text = string.Empty; 例如,Framework不会创建一个空string对象,而是引用一个空字符串常量,并将其设置为Text属性。

在性能测试中,已经显示(在In C#中,我应该使用string.Empty或String.Empty还是“”? post)后两个示例之间确实没有任何有用的区别。 调用Clear()方法肯定是最慢的,但这显然是因为它还有其他工作要做以及清除文本。 即便如此,三个选项之间的性能差异仍然几乎无法察觉。

如果不是真的很深:

清除:从TextBox中删除内容,可能会删除随其分配的资源

  public void Clear() { using (this.TextSelectionInternal.DeclareChangeBlock()) { this.TextContainer.DeleteContentInternal(this.TextContainer.Start, this.TextContainer.End); this.TextSelectionInternal.Select(this.TextContainer.Start, this.TextContainer.Start); } } 

将空字符串(因为string.Empty和“”相等)分配给Text属性只需将空字符串分配给附加属性TextBox.TextProperty:

 public string Text { get { return (string) this.GetValue(TextBox.TextProperty); } set { this.SetValue(TextBox.TextProperty, (object) value); } } 

如果您落后于某些性能差异或内存泄漏,则没有太多(仅在设置文本而不是使用.Clear()时对事件进行一些额外调用)

但是, 在使用MVVM时您无法控制自身 ,因此只有清除文本的方法是使用TextBox将文本设置为binded属性

在标准应用程序中,您可以执行任何您想要的操作(我更喜欢使用专为此目的而设计的.Clear()方法)。

它似乎正在做一些额外的事情,比如检查更改的起源,绑定,更新插入位置以及更新/清除撤消。 分配空字符串时可能不需要大多数。

 ///  /// Callback for changes to the Text property ///  private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { TextBox textBox = (TextBox)d; bool inReentrantChange = false; int savedCaretIndex = 0; if (textBox._isInsideTextContentChange) { // Ignore property changes that originate from OnTextContainerChanged, // unless they contain a different value (indicating that a // re-entrant call changed the value) if (textBox._newTextValue != DependencyProperty.UnsetValue) { // OnTextContainerChanged calls // SetCurrentDeferredValue(TextProperty, deferredTextReference) // Usually the DeferredTextReference will appear in the new entry if (textBox._newTextValue is DeferredTextReference) { if (e.NewEntry.IsDeferredReference && e.NewEntry.IsCoercedWithCurrentValue && e.NewEntry.ModifiedValue.CoercedValue == textBox._newTextValue) { return; } } // but if the Text property is data-bound, the deferred reference // gets converted to a real string; during the conversion (in // DeferredTextReference.GetValue), the TextBox updates _newTextValue // to be the string. else if (e.NewEntry.IsExpression) { object newValue = e.NewEntry.IsCoercedWithCurrentValue ? e.NewEntry.ModifiedValue.CoercedValue : e.NewEntry.ModifiedValue.ExpressionValue; if (newValue == textBox._newTextValue) { return; } } } // If we get this far, we're being called re-entrantly with a value // different from the one set by OnTextContainerChanged. We should // honor this new value. inReentrantChange = true; savedCaretIndex = textBox.CaretIndex; } // CoerceText will have already converted null -> String.Empty, // but our default CoerceValueCallback could be overridden by a // derived class. So check again here. string newText = (string)e.NewValue; if (newText == null) { newText = String.Empty; } textBox._isInsideTextContentChange = true; try { using (textBox.TextSelectionInternal.DeclareChangeBlock()) { // Update the text content with new TextProperty value. textBox.TextContainer.DeleteContentInternal((TextPointer)textBox.TextContainer.Start, (TextPointer)textBox.TextContainer.End); textBox.TextContainer.End.InsertTextInRun(newText); // Collapse selection to the beginning of a text box textBox.Select(savedCaretIndex, 0); } } finally { // if (!inReentrantChange) { textBox._isInsideTextContentChange = false; } } // We need to clear undo stack in case when the value comes from // databinding or some other expression. if (textBox.HasExpression(textBox.LookupEntry(TextBox.TextProperty.GlobalIndex), TextBox.TextProperty)) { UndoManager undoManager = textBox.TextEditor._GetUndoManager(); if (undoManager != null) { if (undoManager.IsEnabled) undoManager.Clear(); } } } 

""创建一个对象,而String.Empty创建任何对象。 因此使用String.Empty更有效。

Refference: String.Empty vs“”

关于.Clear()我没有得到更好的答案然后@ syned的回答。

让我们逐个完成命令。

 txtUserName.Clear(); 

Clear()命令为texbox分配一个空字符串,就像下一个例子一样。 来源 (最佳探索由syned在这一点给出)

 txtUserName.Text = string.Empty; 

现在string.Empty的实际代码是

 static String() { Empty = ""; } 

这意味着您在编译时分配字符串“”。

 txtUserName.Text = ""; 

现在,您只需在编译时将“”字符串直接分配给对象。

小方注释txtUserName.Text = "";txtUserName.Text = string.Empty;更快txtUserName.Text = string.Empty; 资源

 txtUserName.Clear(); 

此代码清除文本框。 它会将Textbox值设置为“”

 txtUserName.Text = string.Empty; 

不创建对象。 这比txtUserName.Text = ""执行得更快;

 txtUserName.Text = ""; 

创建对象并影响性能。

string.Empty字段是一个空字符串文字。 它与空字符串文字常量“”略有不同。 有一个微妙的区别 – 但在某些情况下可能很重要。 它改变了程序的含义

我们在C#程序中使用string.Empty和“” 。 string.Empty字段在运行时由.NET Framework初始化为“”。

您不能将string.Empty用作切换案例,因为it cannot be determined at compile-time by the C# compiler.

这解释了string.empty和“”的区别

Clear()方法不仅仅是从TextBox删除TextBox 。 它会删除所有内容并重置文本选择

嗯..第一个警告,这个答案有可能超出大多数开发人员目前的共识,但这里是:)尝试阅读它直到最后。

这两个(甚至包括我在内的另外一个)完全相同:

 txtUserName.Text = ""; txtUserName.Text = string.Empty; txtUserName.Text = null; 

即使调试配置中的程序集可能会有点不同,我也很肯定在更优化的发布模式下,它们将编译为完全相同的程序集。

如果他们没有出现相同的情况 – 这意味着编译器能够降低本案例代码议程中最优化翻译的能力,换句话说……在其他语言中,这可能来自同一个程序集和来自它的学术观点 – 它应该作为同一个集会出现。 但不是每个编辑都关心那些学术观点的东西:)

关于第三个dude txtUserName.Clear()这是一个不同的情况,我假设你和你一样,这个方法的内部实现实际上只是使用这三个赋值中的一个。
(正如其他人已经提到的那样,除了从文本中删除字符之外,它还做得更多)
但是,如果您认为面向对象 – 假设有人想要创建一个特殊的文本框,其中包含更多要清除的内容 – 对他而言,使用’Clear’方法覆盖将非常方便..如果您使用了clear方法 – 当您从基本文本框更改为新的自定义/特殊texbox时,不要更改代码。

总而言之 – 如果你要使用控件,你应该使用它的方法,这意味着使用’Clear()’方法将更适合你想清除它,特别是如果将来你想要的那一天用您自己的自定义文本框替换该文本框。 所以至少在语法上它是更好的选择..
但是,是的,如果你想要的只是从文本属性中删除字符,它会造成性能。

这是一个测试WPF下每个效率的小程序。

              

 using System; using System.Windows; namespace WpfApplication4 { ///  /// Interaction logic for MainWindow.xaml ///  public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DateTime oldTime, newTime; TimeSpan delta; var iterations = 100000; #region Test performance 1 oldTime = DateTime.Now; for (var i = 0; i < iterations; i++) txtbx1.Text = ""; newTime = DateTime.Now; delta = newTime - oldTime; txtbx1.Text = delta.Milliseconds.ToString(); #endregion #region Test performance 2 oldTime = DateTime.Now; for (var i = 0; i < iterations; i++) txtbx2.Text = string.Empty; newTime = DateTime.Now; delta = newTime - oldTime; txtbx2.Text = delta.Milliseconds.ToString(); #endregion #region Test performance 3 oldTime = DateTime.Now; for (var i = 0; i < iterations; i++) txtbx3.Text = null; newTime = DateTime.Now; delta = newTime - oldTime; txtbx3.Text = delta.Milliseconds.ToString(); #endregion #region Test performance 4 oldTime = DateTime.Now; for (var i = 0; i < iterations; i++) txtbx4.Clear(); newTime = DateTime.Now; delta = newTime - oldTime; txtbx4.Text = delta.Milliseconds.ToString(); #endregion } } } 

那些是我得到的结果:43,40,73,443

并且它是一致的 - 前两个是相同的+/-一个迷你秒或两个,第三个总是稍长,最后一个肯定比其他所有更长。

我认为那就是它的深度:)

有人说String.Empty“”快,但String.EMpty是静态成员,初始化为“”

当我们调用String.EmptyIL会调用

 mscorlib.dll IL_0007: ldsfld string [mscorlib]System.String::Empty 

“”却没有

 IL_001a: ldstr "" 

从逻辑上讲,更有意义的是“”String.Empty更有效