2013-08-29 28 views
25

我在以下三种清除文本框内容的方法之间有点混淆。我正在与WPF合作,并发现所有工作,但我无法找到差异。这三种清除文本框的方法有什么区别?

有人请给我解释一些例子吗?

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

哇......从来没有料想到这么多的答案!洛基你可以请回顾一下答案吗?我添加了赏金,因为我觉得它很有趣,但你可以帮我选择最好的答案。 :) –

+0

@ShadowWizard:嗯,我认为syned答案很好,但需要一些更多的解释,像谢里登答案。请你检查一次,并建议我。 – Rocky

+0

还有5天时间,您还可以对答案进行评论并指出是否有用。 BTW祝贺[this](http://i.stack.imgur.com/FX38P.png)! ;-) –

回答

18

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

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

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

在性能测试中,已经显示(在In C#, should I use string.Empty or String.Empty or “”?后),后两个例子之间确实没有什么有用的区别。调用Clear()方法肯定是最慢的,但显然这是因为它有其他工作要做,并且要清除文本。即便如此,三种选择之间的表现差异仍然几乎不明显。

25

如果不打算真的很深:

清除:从文本框删除内容,并且可以删除它

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); 
    } 
} 
+3

是以同样的方式,但'this.SetValue(TextBox.TextProperty,(object)value)'后面发生了什么;'?认为这是这里的关键。 –

+0

Msdn说,它“只是”设置依赖属性或抛出异常http://msdn.microsoft.com/en-us/library/ms597473.aspx – syned

+0

是的,但这触发*东西*,最终导致文本被分配给定字符串,所以想知道代码在哪里。 –

3

看来,它是做得相当一些额外的东西,如检查对于更改的起源,绑定,更新插入位置和更新/清除撤消。分配空字符串时,大多数情况可能不需要。

/// <summary> 
/// Callback for changes to the Text property 
/// </summary> 
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(); 
     } 
    } 
} 
4

如果你是背后的一些性能上的差异或内存泄漏,有没有太多的(设置文本时,而不是使用.Clear事件只是一些额外的()的调用)

然而,你没有访问控制本身当使用MVVM时,所以只有通过才能清除文本的方式是将文本设置为与TextBox绑定的属性。在标准应用程序中,你可以做任何你想做的事情(我更喜欢使用专为此目的而设计的.Clear()方法)。

1

""创建一个对象,而String.Empty不创建对象。所以使用String.Empty更有效率。

REFFERENCE:String.Empty vs ""

关于.Clear()我因此未得到更好的答案,然后@ syned的答案。

+0

这是不正确的。使用String.Empty并不是更高效。内线“”而不是弦乐弦乐。空音更快。 http://www.dotnetperls.com/string-empty –

+0

@ThomasAndreèLian我同意他们可能会出现''''比'string.Empty'更快的情况,但是当我看到链接http:// forums.asp.net/p/977917/1250790.aspx我仍然有同样的意见,在我上面的答案,并同意你的评论,也有一些特殊情况。 说到内存利用率,最好使用'string.Empty'。 我认为使用''''''或'string.Empty'完全取决于您在程序中处理的要求和情况。 –

1
txtUserName.Clear(); 

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

txtUserName.Text = string.Empty; 

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

txtUserName.Text = ""; 

创建对象并影响性能。

1

让我们一一浏览命令。

txtUserName.Clear(); 

Clear()命令为texbox分配一个空字符串,就像下一个例子。 Source(给出最佳explination通过这一点syned)

txtUserName.Text = string.Empty; 

现在string.Empty它的实际工作代码

static String() 
{ 
    Empty = ""; 
} 

也就是说你指定字符串“”编译时之后。

txtUserName.Text = ""; 

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

小侧面说明txtUserName.Text = "";快于txtUserName.Text = string.Empty;Source

+3

不。这是关于** WinForms **文本框控件,而这里的问题是关于** WPF **文本框控件,它完全不同。 –

+0

你完全正确的。为捕获的荣誉 –

0

有人说的String.Empty更快 “”然而的String.Empty是初始化为静态成员 “”

当我们拨打String.EmptyIL致电

mscorlib.dll 

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

而对于“”它不

IL_001a: ldstr  "" 

SO逻辑上会更有意义的是“”的String.Empty

1

字符串更高效。空字段是空字符串文字。它与空字符串常量“”稍有不同。有一个细微的差别 - 但在某些情况下可能很重要。它改变程序的含义

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

不能使用的String.Empty作为开关的情况下,因为it cannot be determined at compile-time by the C# compiler.

Which explain the differences of string.empty and ""

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

1

嗯..首先警告,这个答案有可能超出当前大多数开发者的共识,但是这里是:)尝试读取它直到最后。

这两个(甚至更多的一个我在内)都完全相同:

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

即使在调试配置组装出来会有点不同,我肯定 在释放模式这是更优化,他们将编译到完全相同的程序集。

如果它们不是相同的 - 这意味着编译器在最优翻译中翻译这种情况的代码议程的能力降低,换句话说......在其他语言中,这可能以同样的集会和从它的学术视野 - 它应该出现为同一个集会。但不是每个编译器都关心那些学术上的东西:)

关于第三个伙计txtUserName.Clear()这是一个不同的情况,我假设你和你一样,这个方法的内部实现实际上或者只是使用其中的一个三个作业..
(正如其他人已经提到,它甚至超越仅仅从文本中删除字符)
但是,如果你认为面向对象 - 假设有人想创建一个特殊的文本框,其中包括例如更多的东西来清除在这里 - 对他来说,使用'清除'方法可以非常方便地覆盖..并且如果您使用了清除方法 - 当您从基本文本框更改为新的定制/特殊文本框时,您不会更改代码。所以总结一下 - 如果你要使用控件,你应该使用它的方法,这意味着使用'Clear()'方法将更适合于当你想清除它,尤其是如果有一天在将来你会想用自己的自定义文本框替换该文本框。所以至少在语法上它是更好的选择。
但是,如果你想要的只是从文本属性中删除字符,它会造成性能。

这里是一个小程序来测试效率每个都在WPF下。

<Window x:Class="WpfApplication4.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <TextBox Name="txtbx1" Grid.Row="0"/> 
    <TextBox Name="txtbx2" Grid.Row="1"/> 
    <TextBox Name="txtbx3" Grid.Row="2"/> 
    <TextBox Name="txtbx4" Grid.Row="3"/> 
</Grid> 

using System; 
using System.Windows; 

namespace WpfApplication4 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    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

而且它是一致的 - 前两个是差不多的+/-迷你第二或第二, 第三总是稍长一些,最后一个肯定比所有其他长。

我认为这是一样深:) :)

相关问题