2013-08-29 30 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

而且它是一致的 - 前兩個是差不多的+/-迷你第二或第二, 第三總是稍長一些,最後一個肯定比所有其他長。

我認爲這是一樣深:) :)

相關問題