2010-01-06 24 views
20

Vì các biến được khai báo bên trong một phương thức chỉ có sẵn trong phương thức đó và các biến được khai báo riêng trong một lớp chỉ có sẵn trong một lớp. Mục đích của từ khóa this là gì? Tại sao tôi muốn để có những điều sau đây:Mục đích của từ khóa 'này' trong C#

private static class SomeClass : ISomeClass 
{ 
    private string variablename; 
    private void SomeMethod(string toConcat) 
    { 
     this.variablename = toConcat+toConcat; 
     return this.variablename; 
    } 
} 

Khi điều này sẽ làm điều tương tự chính xác:

private static class SomeClass : ISomeClass 
{ 
    private string variablename; 
    private void SomeMethod(string toConcat) 
    { 
     variablename = toConcat+toConcat; 
     return variablename; 
    } 
} 

để thực hành các kỹ năng đánh máy của tôi?

+6

'this' từ khóa là ví dụ của lớp, nó sẽ làm điều tương tự. Mọi người có thể thích 'this.variablename' hơn' variablename' để dễ đọc. –

+5

Lưu ý nhỏ: Tôi không nghĩ rằng bạn muốn trả về bất cứ thứ gì từ một phương thức được đánh dấu là 'void' ... –

+1

Trong cấu trúc,' this' có thể được gán cho, điều này khá thú vị. Tôi sẽ xây dựng một câu trả lời lớn về vấn đề này, nhưng câu hỏi là về các lớp học. –

Trả lời

36

Có một vài trường hợp quan trọng:

  • Nếu bạn có một tham số chức năng và một biến thành viên có tên tương tự, bạn cần để có thể phân biệt chúng:

    class Foo { 
        public Foo(int i) { this.i = i; } 
    
        private int i; 
    } 
    
  • Nếu bạn thực sự cần tham chiếu đối tượng hiện tại, thay vì một trong các thành viên của nó. Có lẽ bạn cần phải vượt qua nó để chức năng khác:

    class Foo { 
        public static DoSomething(Bar b) {...} 
    } 
    
    class Bar { 
        public Bar() { Foo.DoSomething(this); } 
    } 
    

    Tất nhiên cũng áp dụng nếu bạn muốn trở một tham chiếu đến đối tượng hiện

+0

oops, ví dụ mã của tôi không có ý nghĩa nhiều. Nên tốt hơn bây giờ. – jalf

+5

Địa điểm thứ ba nơi bạn cần: để kết nối với một hàm tạo khác trong cùng một lớp. –

+2

Ví dụ thứ tư: Để gọi các phương thức mở rộng cho chính bạn. –

28

Trong ví dụ của bạn nó hoàn toàn là một vấn đề của hương vị, nhưng đây là một trường hợp nó không phải là:

private string SomeMethod(string variablename) 
{ 
    this.variablename = variablename; 
    return this.variablename; 
} 

Without this, mã sẽ làm việc khác nhau, gán tham số cho chính nó.

+6

Nó vẫn là một vấn đề của hương vị. Một số lập trình viên đặt tên các trường thể hiện bằng tiền tố gạch dưới và không cần sử dụng 'this'. –

+8

Đó là vấn đề về hương vị nhưng, như bạn chỉ ra, có một sở thích cụ thể có thể dẫn đến những lỗi nhỏ, khó phát hiện. Sở thích của tôi là luôn sử dụng 'this' cho các biến mẫu. – tvanfosson

+5

@Martinho Fernandes - trừ khi bạn phạm sai lầm và không tuân theo hướng dẫn tùy ý, thì bạn thực sự bối rối. Tốt hơn nhiều để sử dụng tính năng ngôn ngữ hơn là một cơ chế đặt tên tùy ý để cho biết sự khác biệt IMO. – tvanfosson

4

Bạn cần this nếu tham số phương pháp của bạn có cùng tên với trường.

private string variablename; 
private void SomeMethod(string variablename) 
{ 
    this.variablename = variablename+variablename; 
    return this.variablename; 
} 
3
  1. this nghĩa thành viên lớp dụ hiện tại của bạn không
    a. thành viên lớp cơ sở của bạn
    b. phạm vi thành viên
    c. thành viên tĩnh
  2. Để làm cho mã của bạn dễ đọc hơn.
3

Điều đầu tiên mà tôi nghĩ là dễ đọc và/hoặc sở thích cá nhân.

Thỉnh thoảng khi tôi làm việc với một lớp khá lớn ... hoặc một lớp học có lớp cơ sở (nơi tôi không thể "xem" một số biến) ... Tôi sử dụng từ khóa "này" ... intellisense trong Visual Studio.

0

Đây là vấn đề về phong cách chủ yếu. Nếu phương thức của bạn có tên biến giống với một thành viên lớp riêng tư, việc sử dụng tên này sẽ giúp phân biệt. Điều này có khả năng ngăn chặn các lỗi ngớ ngẩn.

0

sử dụng chung là với đối số nhà xây dựng có cùng tên:

public SomeClass(string variablename) 
{ 
    this.variablename = variablename; 
} 
4

Trong hầu hết các trường hợp, sử dụng đơn giản this clutters mã. Tuy nhiên, tôi đã nhìn thấy nó được sử dụng bởi các lập trình viên khác, có lẽ là để kích hoạt intellisense cho các thành viên của lớp địa phương.

Từ khóa this cũng được yêu cầu để sử dụng trong các phương pháp mở rộng.

public static class MyExtensions 
{ 
    public static int WordCount(this String str) 
    { 
     return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length; 
    } 
} 
15

Có nhiều trường hợp điều này hữu ích. Dưới đây là một ví dụ:

class Logger { 
    static public void OutputLog (object someObj) { 
     ... 
    } 
} 

class SomeClass { 
    private void SomeMethod() { 
     Logger.OutputLog (this); 
    } 
} 

Đây là một ví dụ khác. Giả sử tôi đang viết Luồng.Ra phương pháp mà kết quả đầu ra một đối tượng, và trả về một tham chiếu đến dòng riêng của mình, như vậy:

class Stream { 
    public Stream Out (object obj) { 
     ... code to output obj ... 
     return this; 
    } 
} 

Sau đó, người ta có thể sử dụng cuộc gọi này ra trong một chế độ xích:

Stream S = new Stream (...); 
S.Out (A). Out (B). Out (C); 
+1

+1 - bạn thường cần sử dụng "điều này" trong một phương pháp mà bạn muốn truyền cho chính mình một số đối tượng khác. –

+0

@Eric: Chính xác, tóm tắt tốt. Ngoài ra, như trong ví dụ thứ hai tôi đã cung cấp ở trên, khi bạn muốn * trả lại * cho mình từ một phương pháp. – Tarydon

4

Thứ nhất, ví dụ của bạn thiếu sót vì bạn đã đánh dấu lớp là tĩnh, vì vậy nó không thể được khởi tạo.

Bất kể, this chỉ đơn giản là tham chiếu đến phiên bản hiện tại. Nó có thể được sử dụng để giải quyết xung đột giữa các biến địa phương và các biến thành viên, ví dụ:

public class Foo 
{ 
    private string baz; 

    public void Bar(string baz) 
    { 
     this.baz = baz; 
    } 
} 

Nó cũng có thể được sử dụng chỉ đơn giản như một đối tượng theo đúng nghĩa của nó, ví dụ:

public class Foo 
{ 
    public List<Foo> GetList(string baz) 
    { 
     var list = new List<Foo>(); 
     list.Add(this); 

     return list; 
    } 
} 

(Không rằng ví dụ này là đặc biệt hữu ích, nhưng bạn sẽ có được ý tưởng)

Edit:. Một nhiều ví dụ thực tế là mô hình sự kiện trong .NET:

public class Foo 
{ 
    public EventHandler SomeEvent; 

    public void Bar() 
    { 
     if (SomeEvent != null) 
     { 
      SomeEvent(this, EventArgs.Empty); 
     } 
    } 
} 
+0

một lần nữa. . . cảm ơn critiqing một ví dụ crappy tôi whipped với pad lưu ý. . . ;) – andrewWinn

3

Ngoài Javascript có lẽ, "điều này" chủ yếu là từ khóa giữ chỗ và hữu ích nhất là làm cho mục đích của bạn rõ ràng khi viết một đoạn mã.

Về cơ bản, tính năng này sẽ giúp dễ đọc.

2

Tôi trân trọng không đồng ý với một số khác áp phích. Trong C#, nó không chỉ là vấn đề về hương vị; nó cũng phù hợp với các nguyên tắc về phong cách C# của Microsoft (cả nội bộ lẫn bên ngoài, mặc dù chúng dường như không phải là hướng dẫn riêng của chúng trong nội bộ).

Có ví dụ về trường hợp khi các ký hiệu mà bạn sử dụng sẽ không hoạt động:

private void DoSomething(object input) 
{ 
    input = input; 
} 

Thay vào đó, bạn sẽ cần phải sử dụng các ký hiệu sau:

private void DoSomething(object input) 
{ 
    this.input = input; 
} 
+1

Có một lý do là những nguyên tắc này chứ không phải là một quy tắc của pháp luật có thể bị trừng phạt bởi cái chết. Có nhiều nguyên tắc có thể không được sử dụng. (Xem tranh luận về các giao diện gắn thẻ so với các thuộc tính meta) http://stackoverflow.com/questions/983037/are-tag-or-marker-interfaces-obsolete –

+0

Các nguyên tắc về phong cách là vấn đề về hương vị. –

+0

Tôi không đồng ý rằng các nguyên tắc về phong cách là chủ quan, nhưng những gì bạn đang nói là tương đương, "Viết hoa tiêu đề sách là một vấn đề về hương vị." Nó không phải là, trên thực tế, một vấn đề "hương vị". Đó là vấn đề của tiêu chuẩn được chấp nhận để tạo kiểu chữ. –

3

Trước hết, này là cần thiết khi một phương thức lớp cần chuyển một tham chiếu đến đối tượng tới một phương thức nào đó trong một lớp khác.

Ví dụ: "này"

class Image 
{ 
    void Refresh() 
    { 
     Screen.DrawImage(this); 
    } 
} 

Không giống như một số kịch bản khác, nơi sử dụng hoặc không sử dụng là một vấn đề về phong cách, hoặc một phương tiện để giải quyết một sự mơ hồ nhân tạo.

2

this là trường hợp của lớp và trong ví dụ bạn cho chúng tôi biết: bạn sử dụng this để tham chiếu đến trường có tên variablename.

Nếu bạn có biến cục bộ hoặc tham số có cùng tên, bạn sẽ cần phải có cách phân biệt giữa chúng. Trong trường hợp đó, this sẽ tham chiếu đến trường, trong khi không bắt đầu bằng this là biến hoặc tham số cục bộ.

Bạn nên có quy ước đặt tên giúp bạn khác nhau giữa các trường và người dân địa phương. Điều này sẽ giúp bạn tiết kiệm từ những rắc rối có thể xảy ra nếu sau này bạn thêm một địa phương có cùng tên cho phương thức của bạn. (Kể từ mã mà không this sau đó sẽ phá vỡ ...)

0

1) Thứ nhất, và quan trọng nhất, là một tình huống khi một đối tượng cần phải vượt qua một tham chiếu đến chính nó:

public class Element{ 
//... 
public Element Parent; 
public Element Root() 
{ 
if(Parent == null) 
    return this; 
return Parent.Root(); 
} 
} 
public void OnEvent() 
{ 
Event(this, new EventArgs()); 
} 

Trong giao diện thông thạo:

lớp công khai Truy vấn { truy vấn công cộng Thêm (Tham số tham số) {_listThêm (tham số); trả lại điều này; }}

2) Thứ hai, trong và phương pháp khuyến nông:

public class Extension 
{ 
public Element Root(this Element element) { 
    if(element.Parent == null) 
    return element; 
    return element.Parent.Root(); 
} 
} 

3) Thứ ba, và bạn thực sự không cần nó, để phân biệt các thông số từ các thành viên lớp. Bạn không cần nó, bởi vì một quy ước mã hóa tốt giúp bạn tiết kiệm từ việc sử dụng từ khóa 'này'.

public class Element 
{ 
public Element Parent; 
publlc void SetParent(Element parent) 
{ 
    // this.Parent = parent; // see, you don't need it 
    Parent = parent; 
} 
} 
//... 
public class Element 
{ 
public Element _parent; 
public Element Parent { get { return _parent; } } 
publlc void SetParent(Element parent) 
{ 
    // this._parent = parent; // see, you don't need it 
    _parent = parent; 
} 
} 
5

Ngoài việc "định hướng lĩnh vực" và "đi qua một tài liệu tham khảo của isntance hiện tại" câu trả lời (đã được đưa ra), có một kịch bản thêm nơi this là cần thiết; để gọi các phương thức mở rộng trên dụ hiện tại (tôi bỏ qua việc sử dụng this trong tuyên bố một phương pháp mở rộng, vì đó không phải là khá ý nghĩa tương tự như câu hỏi):

class Foo 
{ 
    public void Bar() 
    { 
     this.ExtnMethod(); // fine 
     ExtnMethod(); // compile error 
    } 
} 
static class FooExt 
{ 
    public static void ExtnMethod(this Foo foo) {} 
} 

Để công bằng, đây không phải là một kịch bản phổ biến. Một một trong nhiều khả năng chỉ đơn giản là để làm cho mã dễ đọc hơn, ví dụ:

public bool Equals(Foo other) { 
    return other != null && this.X == other.X && this.Y == other.Y; 
} 

Ở phía trên (hoặc tương tự cho Compare, Clone vv), mà không có sự this. Tôi tìm thấy nó một chút ... "không cân bằng".

+0

Tôi "đã" sử dụng điều này khi lớp cơ sở có các phương thức mở rộng để cung cấp một giao diện đơn giản hơn cho một số hoạt động. –

+0

Và đây thực sự là trường hợp đặc biệt của trường hợp "vượt qua tham chiếu đến chính bạn", ngoại trừ trường hợp đó là (cú pháp) phủ đường. –

0

Có một nguyên tắc nên hướng dẫn bạn trong việc quyết định có sử dụng 'điều này' hay không. Bạn có cần tham khảo cụ thể cho trường hợp này của lớp không? Nếu bạn làm vậy, hãy dùng 'this'. Nếu không, hãy để nó ra.

Ví dụ về trình ghi nhật ký một áp phích khác được cung cấp là một ví dụ điển hình về điều này. Anh không thể dựa vào điều này, vì anh cần chính đối tượng đó.

Không có điểm nào về việc sử dụng 'this' làm tiền tố cho một phương thức của chính lớp đó, trong chính lớp đó, vì nó là ẩn.

0

tôi không thể giúp đỡ, nhưng ...

if (this == null) 
    throw new NullReferenceException(); 

[KIDDDIIIING !!!]

0

Một kịch bản I'v đã tìm thấy:

private int value; 
public int Value 
{ 
    get { return this.value; } 
    set { this.value = value; } //without this it doesn't make sense 
} 
+1

điều này sẽ không hoạt động, vì bạn đã đặt tên trường sao lưu '_value' chứ không phải' giá trị'. – Oliver

+0

@Oliver, yap +1 cho bạn, do tôi ấn định. – Dariusz

Các vấn đề liên quan