this operator in C#.net , usage and benefits? [duplicate] - c#-4.0

This question already has answers here:
When do you use the "this" keyword? [closed]
(31 answers)
In C#, is "this" keyword required? [duplicate]
(6 answers)
Closed 8 years ago.
since many years i'm trying to figure out that what does 'this' do in c#.net
e.g.
private string personName;
public Person(string name)
{
this.personName = name;
}
public override string ToString()
{
return this.personName;
}
}

The this keyword allows you to explicitly refer to a member of the current instance.
In your case, you can just as easily leave it off - the rules in C# will find the member variable.
However, if you use a parameter with the same name as a member variable, or have a local with the same name, using this specifies which variable to use. This allows you to do:
private string personName;
public Person(string personName)
{
// this finds the member
// refers to the argument, since it's in a more local scope
this.personName = personName;
}
Tools like StyleCop enforce the use of this everywhere, since it completely removes any ambiguity - you're explicitly saying you want to set a member (or call a function, etc) within the current instance.

this refers to the object that the method belongs to. It can be used - like demonstrated in the other answers - for scope choosing. It can also be used when you want to use the current object as an entire object(that is - not a specific field, but the object as a whole) - for example:
public class Person{
private string name;
private Person parent;
public Person(string name,Person parent=null;){
this.name = name;
this.parent = parent;
}
public Person createChild(string name){
return new Person(name,this);
}
}

this refer to the instance of the class. Usually you don't use it as it becomes noise,but in some case it's important to use it.
public class Foo
{
private string bar;
public Foo(string bar)
{
//this.bar refer to the private member bar and you assign the parameter bar to it
this.bar = bar;
//Without the this, the bar variable in the inner scope bar, as in the parameter.¸
//in this case you are assigning the bar variable to itself
bar = bar;
}
}

Related

Overriding parent methods with contravariant arguments

Basically, I want to override a parent class with different arguments. For example:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
Then override that class, something like:
class HoldMore extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
set(value, value2);
}
override public function set(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
Obviously this will return an error, Field set overloads parent class with different or incomplete type. Is there a way around this? I tried using a public dynamic function, and then setting set in the new() function, but that gave a very similar error. Any thoughts?
This is just a complement to #stroncium's answer, which is totally correct.
Here is an example how it could look like:
class Hold<T> {
public var value:T;
public function new(value:T) {
set(value);
}
public function set(value:T) {
this.value = value;
}
}
class HoldMore<T> extends Hold<T> {
public var value2:T;
public function new(value:T, value2:T) {
super(value);
setBoth(value, value2);
}
// you cannot override "set" with a different signature
public function setBoth(value:T, value2:T) {
this.value = value;
this.value2 = value2;
}
}
alternatively, you could use an array as parameter or a dynamic object holding multiple values in order to "set" them using the same method, but you loose some of the compiler's type checking.
If you wrote the base class you could add an optional argument to it, this would be a workaround though, not directly what you want to do.
In the current state it totally won't work. There is not only 1 problem, but few of them:
Type T is meaningless in context of this new class, you should either use some concrete type or template this class over T.
You can not change the number of arguments of function when overriding it. However you can add another function(with a different name) to accept 2 arguments and do what you want (which is the way you would use in most languages, by the way).
I don't really understand how you see a contravariance problem there. The actual problem is that haxe doesn't support function overload. (It actually does, the function signature is name + full type, but that's not what you would want to write nor support, and is mostly used for js/java externs.)
Unfortunately the language doesn't allow it.

How to display the ToString of an object which is in a ListBox?

I have a class which holds the string I want to display and an id for that item.
ref class ListBoxItem {
private:
int id;
String ^ name;
public:
ListBoxItem(int id, const char * name) { this->id = id; this->name = gcnew System::String(name); }
virtual String ^ ToString() new { return name; }
};
And I add each item to the ListBox like this:
for(list<string>::iterator i = listItems.begin(); i != listItems.end(); i++)
listBoxItems->Items->Add(gcnew ListBoxItem(2, (*i).c_str()));
This will produce a ListBox with the correct number of items, but all the items are called "ListBoxItem".
Instead, I want the ListBox to display the string which is produced when the ToString method is invoked on ListBoxItem.
You didn't say whether you were using WinForms or WPF, but I believe this answer is valid for either.
(Note: There is a class named ListBoxItem in the framework. You might want to pick a different class name.)
I believe the issue is here:
virtual String ^ ToString() new { return name; }
^^^
This means you're creating a brand new ToString method, which doesn't have anything to do with the Object.ToString method. When the ListBox calls ToString, it doesn't have your class definition, so it just calls Object.ToString(), which you haven't changed.
Switch it to this, and you should be good:
virtual String ^ ToString() override { return name; }
^^^^^^^^

Regarding String functionality

I was developing the below class..
public class Test1
{
public void method(Object o)
{
System.out.println("Object Verion");
}
public void method(String s)
{
System.out.println("String Version");
}
public static void main(String args[])
{
Test1 question = new Test1();
//question.method(question);
question.method(null);
}
}
Now upon executing it invokes string version as output So please advise here string is treated as null and what should we pass to invoke the object version.Thanks in advance
All other things being equal, the most-specific method will be called. From the JLS:
15.12.2.5. Choosing the Most Specific Method
If more than one member method is both accessible and applicable to a
method invocation, it is necessary to choose one to provide the
descriptor for the run-time method dispatch. The Java programming
language uses the rule that the most specific method is chosen.
The informal intuition is that one method is more specific than
another if any invocation handled by the first method could be passed
on to the other one without a compile-time type error.
question.method(null) could mean either the String or Object overload, but since String is more specific (narrower) than Object, the String overload is the method that is called.

Problem binding a bean property to an element in JSF

I have an input (JSF) that should be bound to a property in my bean. This property represents another bean and has an auxiliar method that checks if it's null (I use this method a lot).
The problem is that the binding is failing to get the proper getter and setter. Instead of reading the method that returns the bean, it reads the one that return a boolean value.
The property name is guest. The methods are:
getGuest;
setGuest;
isGuest (checks if guest is null).
JSF is trying to bind the object to isGuest and setGuest, instead of getGuest and setGuest.
I cannot rename isGuest to guestIsNull or something, because that would'nt make to much sense (see the class below).
Finally, my question is: how can I bind this property to the object without renaming my methods? Is it possible?
I also accept suggestions of a better method name (but the meaning must be the same).
Entity
#Entity
public class Passenger {
private Employee employee;
private Guest guest;
public Passenger() {
}
#Transient
public boolean isEmployee() {
return null != this.employee;
}
#Transient
public boolean isGuest() {
return null != this.guest;
}
#OneToOne
public Employee getEmployee() {
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
#OneToOne
public Guest getGuest() {
return this.guest;
}
public void setGuest(Guest guest) {
this.guest = guest;
}
}
JSF
<h:inputText value="#{passenger.employee}" />
<h:inputText value="#{passenger.guest}" />
Change the method name to isGuestNull.
The problem you're seeing is due to the fact that the EL lets you use getFoo or isFoo as the naming style for getter methods that return booleans.
No, that's not possible. You've to rename them.
Another way is to add a single getter returning an enum which covers all cases.
public enum Type {
GUEST, EMPLOYEE;
}
public Type getType() {
return guest != null ? Type.GUEST
: employee != null ? Type.EMPLOYEE
: null;
}
with
<h:something rendered="#{passenger.type == 'GUEST'}">
Binding to any property using any method is possible and quite easy if you create your custom ELResolver (apidocs). elresolvers are registered in faces config, and they are responsible, given an Object and a String defining a property, for determining the value and type of the given properties (and, as the need arises, to change it).
You could easily write your own ELResolver that would only work for your chosen, single type, and use (for example in a switch statement) the specific methods you need to write and read properties. And for other types it would delegate resolving up the resolver chain. It's really easy to do, much easier than it sounds.
But don't do it. The standard naming pattern of properties predates EL by many years. It is part of the JavaBeans™ standard - one of the very few undisputed standards in Javaland, working everywhere - from ant scripts, through spring configuration files to JSF. Seeing methods isPerson and getPerson in one class actually makes me fill uneasy, as it breaks something I always take for granted and can always count on.
If you like DDD and want to have your method's names pure, use an adapter. It's easy, fun, and gives a couple of additional lines, which is not something to sneer at if you get paid for the ammount of code produced:
public class MyNotReallyBean {
public String checkName() { ... }
public String lookUpLastName() { ... }
public String carefullyAskAboutAge() { ... }
public class BeanAdapter {
public String getName() { return checkName(); }
public String getLastName() { return lookUpLastName(); }
public String getAge() { return carefullyAskAboutAge(); }
}
private static BeanAdapter beanAdapter = new BeanAdapter();
private BeanAdapter getBeanAdapter(){ return beanAdapter; }
}

Resharper intellisense confusion

Today I had something weird happen in my copy of Resharper 5. I have a class that looks like this:
public class Foo
{
public string Username { get; private set; }
public Foo (string userName) { Username = userName; }
public void Bar()
{
DoWork(Username);
}
public void DoWork(string userName) { }
}
When I start to type DoWork(us I get the following from intellisense:
Notice that it's pulling up the constructor argument, and it ends with a colon: userName:
What's going on here?
EDIT:
As Reed answered below, this is a new C# 4 feature called Named and Optional Arguments. It's purpose is to allow you to specify the name of an argument, rather than it's position in a parameter list. so you don't have to remember the position of an argument in the argument list to use it (though this is largely meaningless with intellisense). It does make optional arguments easier to use though.
Thanks Reed.
This is Resharper providing intellisense support for Named and Optional Arugments.
C# 4 added support for these. You can now have a method defined like this:
public void DoWork(int someArgument = 3, string userName = "default")
{
// ...
If you want to call this with a different "userName" but leave the default for other parameters, you can do:
this.DoWork(userName: "FooUser");
Resharper 5 adds support for this syntax in intellisense.
You didn't include the ; at the end of userName
public Foo (string userName) { Username = userName; }

Resources