My class that passes itself to a method in another class. This external method (the last line in the code below) alters the object I’m passing accordingly, returns control, and continues on its merry way. But the last line ThisPaymentGateway.Process(ref this);
says this at design time:
Cannot pass 'this' as a ref or out argument because it is read-only***
There are no read-only properties there. How can I resolve this?
using System;
namespace Something
{
namespace Finance
{
namespace Donations
{
public class Electronic1 : Donation
{
private PaymentGateway ThisPaymentGateway { get; set; } = new PaymentGateway();
public void RunController()
{
if (DonorType.ToUpper() == "IND" && (PaymentMethod.ToUpper() == "CREDIT CARD" || PaymentMethod.ToUpper() == "ECHECK"))
{
ThisPaymentGateway.Process(ref this);
}
}
}
}
}
}
Remove "ref" from the call and Process method signature
If you just want to "alter the object" and then return, you don't need to pass it by ref anyway. Classes are already reference types and therefore if you change the object properties in Process it will change them in the source object.
First of all do not use strings instead of enum
, it may not be obvious but you're performing culture aware comparison and you're converting PaymentMethod
to uppercase using current culture rules. What does it mean? Schoolbook example is Turkish locale: "ind".ToUpper() != "IND"
. If you need to compare two strings regardless case use String.Equals(PaymentMethod, "IND", StringComparer.InvariantCultureIgnoreCase)
(here I assume, because one string is hard-coded that you want to perform comparison using invariant culture rules but also ordinal comparison may be appropriate).
In C# you do not need to declare namespace in that way, this syntax is valid:
namespace Something.Finance.Donations {
}
About your question: variables passed with ref
may be changed. this (let's imagine it's a variable, just imagine...) obviously cannot be changed then you have that compiler error.
Read this:
static void ChangeAnimalWithRef(ref Animal animal) {
animal = new Cat();
Debug.Assert(animal.GetType() == typeof(Cat));
}
static void ChangeAnimalWithoutRef(Animal animal) {
animal = new Cat();
Debug.Assert(animal.GetType() == typeof(Cat));
}
void Test1() {
Animal animal = new Dog();
Debug.Assert(animal.GetType() == typeof(Dog));
ChangeAnimalWith(ref animal);
Debug.Assert(animal.GetType() == typeof(Cat));
}
void Test2() {
Animal animal = new Dog();
Debug.Assert(animal.GetType() == typeof(Dog));
ChangeAnimalWithoutRef(animal);
Debug.Assert(animal.GetType() == typeof(Dog));
}
Think them as a pointer to a variable instead of the value of that variable (in C# parameters are passed by value, you need ref
and out
to pass them by reference).
If you own ThisPaymentGateway.Process()
method I'd bet you just do not need ref
modifier and you're just used to C++ references with &
. In C# things are different.
If, for any obscure reason, you do not own that method and its signature cannot be changed then you have two options:
1) Create a dummy variable:
Electronic1 dummy = this;
ThisPaymentGateway.Process(ref dummy);
Debug.Assert(Object.ReferenceEquals(dummy, this), "Ooops, what are we supposed to do?");
2) Call that function from outside the class (and change your logic little bit):
var obj = new Electronic1();
if (obj.CanRunController())
obj.ThisPaymentGateway.Process(ref obj);
I strongly doubt you need any of them, it's just for completeness.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With