Pass a class object (this) by reference

J

Jay Douglas

Hello, I am needing to pass a class object (this) by reference to a method
in a different class. When I do the following code I get the error (Cannot
pass '<this>' as a ref or out argument because it is read-only) .. Is there
any way to make <this> not read-only?

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(ref taskId);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}

All suggestions are appreicated.

Thanks!
 
W

William Stacey

Your trying to pass ref to taskId which is an int. In your GetTaskFromId
method, the signature is a Task type. I think you may want
"data.GetTaskFromId( data );" You don't need the "ref" to give TaskData
access to members of this object. Remove the ref and change the taskId to
data in your method call, and this should do what you want.
--wjs mvp
 
J

Jay Douglas

You know what, I hastily broke down that code. The code I provided is
incorrect. Please view the new code for the error "Cannot pass '<this>' as
a ref or out argument because it is read-only" The line that I adjusted is
"data.GetTaskFromId(this);" in the Task class. My appologies for not double
checking my post.

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(this);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}



--
Jay Douglas
Fort Collins, CO



William Stacey said:
Your trying to pass ref to taskId which is an int. In your GetTaskFromId
method, the signature is a Task type. I think you may want
"data.GetTaskFromId( data );" You don't need the "ref" to give TaskData
access to members of this object. Remove the ref and change the taskId to
data in your method call, and this should do what you want.
--wjs mvp

Jay Douglas said:
Hello, I am needing to pass a class object (this) by reference to a method
in a different class. When I do the following code I get the error (Cannot
pass '<this>' as a ref or out argument because it is read-only) .. Is there
any way to make <this> not read-only?

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(ref taskId);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}

All suggestions are appreicated.

Thanks!
 
J

Jon Skeet [C# MVP]

Jay Douglas said:
You know what, I hastily broke down that code. The code I provided is
incorrect. Please view the new code for the error "Cannot pass '<this>' as
a ref or out argument because it is read-only" The line that I adjusted is
"data.GetTaskFromId(this);" in the Task class. My appologies for not double
checking my post.

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

I don't see *why* you're trying to pass it by reference in the first
place - could you explain?

You *may* misunderstand what passing parameters by reference is really
about. See
http://www.pobox.com/~skeet/csharp/parameters.html
 
B

bob holder

Jay Douglas said:
You know what, I hastily broke down that code. The code I provided is
incorrect. Please view the new code for the error "Cannot pass '<this>' as
a ref or out argument because it is read-only" The line that I adjusted is
"data.GetTaskFromId(this);" in the Task class. My appologies for not double
checking my post.

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(this);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}



--
Jay Douglas
Fort Collins, CO



William Stacey said:
Your trying to pass ref to taskId which is an int. In your GetTaskFromId
method, the signature is a Task type. I think you may want
"data.GetTaskFromId( data );" You don't need the "ref" to give TaskData
access to members of this object. Remove the ref and change the taskId to
data in your method call, and this should do what you want.
--wjs mvp

Jay Douglas said:
Hello, I am needing to pass a class object (this) by reference to a method
in a different class. When I do the following code I get the error (Cannot
pass '<this>' as a ref or out argument because it is read-only) .. Is there
any way to make <this> not read-only?

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(ref taskId);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}

All suggestions are appreicated.

Thanks!

The problem might be the passing of the Task object before it is completely
constructed.

bob
 
J

Jay Douglas

Jon,

The reason I want to pass (this) is because the data class makes multiple
changes to the task object and I don't want to have to reset all the
properties back in the Task object. What I'm trying to avoid is needing to
do something like:

(This is how I currently do it with out the references, the data class
returns a new task object)
Task task data.GetTaskFromId(this);
this.Property1 = task.Property1
this.Property2 = task.Property2

I need to break out all of the data classes because a project implementation
may use the database (MS SQL, LDAP, MySQL) or the file system.

I would like to change (this) in another class without needing to reset all
of the properties. This is a has been a development issue for me across the
board. I'm not opposed to a different development pattern to address this
issue. I would just like to come up with something.

All suggestions are appreciated.
--
Jay Douglas
Fort Collins, CO
 
J

Jon Skeet [C# MVP]

Jay Douglas said:
The reason I want to pass (this) is because the data class makes multiple
changes to the task object and I don't want to have to reset all the
properties back in the Task object.

You don't. As I thought, you don't quite understand what pass-by-
reference does, or what reference types are in .NET. Read the page I
linked to before.

I would like to change (this) in another class without needing to reset all
of the properties.

You can change the properties *of* "this" but you can't change which
object "this" is a reference to. It doesn't really make sense (IMO) to
be able to do

this = new Task();

which is what you'd be allowing yourself to do if you could pass this
by reference.
 
1

100

Hi Jay,
Just remove the ref modifier form the task parameter of GetTaskFromId
method. Since Task is a class (reference type) you pass references to its
instances anyway. Making task parameter *ref* means that changing the value
of the formal parameter (task) will change the value of the actual parameter
used for the method call. You cannot change *this*. That's why the compiler
reports an error and says that *this* is readonly.

So, once again my siggestion is to remove the *ref* modifier from the *task*
parameter of GetTaskFromId method.

HTH
B\rgds
100

Jay Douglas said:
You know what, I hastily broke down that code. The code I provided is
incorrect. Please view the new code for the error "Cannot pass '<this>' as
a ref or out argument because it is read-only" The line that I adjusted is
"data.GetTaskFromId(this);" in the Task class. My appologies for not double
checking my post.

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(this);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}



--
Jay Douglas
Fort Collins, CO



William Stacey said:
Your trying to pass ref to taskId which is an int. In your GetTaskFromId
method, the signature is a Task type. I think you may want
"data.GetTaskFromId( data );" You don't need the "ref" to give TaskData
access to members of this object. Remove the ref and change the taskId to
data in your method call, and this should do what you want.
--wjs mvp

Jay Douglas said:
Hello, I am needing to pass a class object (this) by reference to a method
in a different class. When I do the following code I get the error (Cannot
pass '<this>' as a ref or out argument because it is read-only) .. Is there
any way to make <this> not read-only?

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(ref taskId);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}

All suggestions are appreicated.

Thanks!
 
W

William Stacey

You still don't need the "ref" in there, unless I miss what your trying to
do. Remove the ref and see if that does what you need.

Jay Douglas said:
You know what, I hastily broke down that code. The code I provided is
incorrect. Please view the new code for the error "Cannot pass '<this>' as
a ref or out argument because it is read-only" The line that I adjusted is
"data.GetTaskFromId(this);" in the Task class. My appologies for not double
checking my post.

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(this);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}



--
Jay Douglas
Fort Collins, CO



William Stacey said:
Your trying to pass ref to taskId which is an int. In your GetTaskFromId
method, the signature is a Task type. I think you may want
"data.GetTaskFromId( data );" You don't need the "ref" to give TaskData
access to members of this object. Remove the ref and change the taskId to
data in your method call, and this should do what you want.
--wjs mvp

Jay Douglas said:
Hello, I am needing to pass a class object (this) by reference to a method
in a different class. When I do the following code I get the error (Cannot
pass '<this>' as a ref or out argument because it is read-only) .. Is there
any way to make <this> not read-only?

I have simplified the following code. There is a Task class and a Data
Class. I am trying to pass the task class by ref to the data class.

public class Task
{
public Task(int taskId)
{
TaskData data = new TaskData();
data.GetTaskFromId(ref taskId);
data.Close();
}
}

public class TaskData
{
public void GetTaskFromId(ref Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));

SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}

All suggestions are appreicated.

Thanks!
 
J

Jay Douglas

Jon,
It looks like I was really missing the big picture. You advise was
really helpful and gave me a sold answer. Here is the modified code that
works:

public class Task
{
public Task(int taskId)
{
this.taskId = taskId;

TaskData data = new TaskData();
data.GetTaskFromId(this);
data.Close();

Console.WriteLine(this.Name); // Out puts the change
// that the data class
// made to the Task object
}
}

public class TaskData
{
internal void GetTaskFromId(Task task)
{
SqlCommand cmd = new SqlCommand("sp_Task_GetByID_Select", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@TaskID", task.TaskId));
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
task.TaskId = Convert.ToInt32(reader["TaskId"]);
task.Name = reader["Name"].ToString();
task.Description = reader["Descr"].ToString();
}

reader.Close();
cmd.Dispose();

}
}

--
Jay Douglas
Fort Collins, CO
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top