0

I am passing a classobject(Cache class object) as a reference in a constructor of Myclass.

public class Test{
  static void Main(string[] args){
     Cache<string, string> cache;
     Myclass obj = new MyClass(ref cache);
     obj.doSomething();
     Console.WriteLine(cache.key); // I want this value to get changed according to the doSomething Method
     Console.WriteLine(cache.value);// I want this value to get changed according to the doSomething Method
  }
}

Now in MyClass, I want to set the value of this cache

public class Myclass{
    ref Cache<string, string> C;
    Myclass(ref Cache<string, string> cache){
        this.C = cache;
    }
    void doSomething(){
        C.key = "key";
        C.value = "value"
    }
}

I want that changing the value of cache in Myclass should reflect in Test Class. But I am not sure how to achieve this. Any help would be appreciated.

Here is the complete scenario which I am trying to do. We have a no of multiple orgs and there are some properties of the org which are same for some org and we don't want to compute those property again and again as it is costly operation. That properties are computed in doSomethingMethod above.

My cache is actually a list. And this cache variable will be passed in the multiple orgs. So in dosomething method I want to check whether the cache is being set or not by any other org and if the key is present I will not compute operation and I will just return from cache.

Devendra Verma
  • 975
  • 2
  • 10
  • 24
  • 7
    `ref` shouldn't be required here at all. Try not using it at all. – Damien_The_Unbeliever Jan 27 '21 at 08:18
  • What is Cache? I think you need to rethink the design. What is your goal? Please try to better explain your issue, dev env, data types & expected result, as well as to share more or less code (no screenshot), images or sketches of screens, user stories or scenario diagrams, as well as sample like if it was a unit test or an API usage. As I can deduct from the code provided, changing Key and Value should be reflexted everywhere... this I don't understand this design shown here. –  Jan 27 '21 at 08:20
  • Hi @Damien_The_Unbeliever thanks for the comment. It means that if I just pass cache object(without ref keyword) will it be passed as a reference? – Devendra Verma Jan 27 '21 at 08:22
  • Passing a class instance as a parameter of a method, you pass the reference by the value of this reference, so when changing properties, they are live changed, in the original object. But assigning the variable, you don't change the original reference. Using ref will "pass a reference to the reference"... to modify the reference itself: assigning the reference with a new instance will disconnect the old for the new even from teh caller point of view. –  Jan 27 '21 at 08:23
  • [Passing a class as a ref parameter in C# does not always work as expected. Can anyone explain?](https://stackoverflow.com/questions/9996359/passing-a-class-as-a-ref-parameter-in-c-sharp-does-not-always-work-as-expected) and [Passing Reference Types by Reference](https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/passing-reference-type-parameters#passing-reference-types-by-reference) –  Jan 27 '21 at 08:25
  • @OlivierRogier I have updated the question with the scenario, I am trying to achieve. – Devendra Verma Jan 27 '21 at 08:29
  • 1
    @DevendraVerma Sometimes describing goals can be helpful in helping, as well as understanding coding issues, but to solve code issues, Stack Overflow's mission, we need code. Reading several sentences that explain like a client's specifications, especially since I am French and not advanced in English, is difficult here for me, and also for anyone slower than having the code, even wrong, bad or pseuco-code instead of literature. So please indicate what minimum definition for `Cache`, this is not a list, but seems to be liek a dictionary, as well as a sample as requested in my previous comment. –  Jan 27 '21 at 08:34
  • @DevendraVerma For example, I don't understand "*We have a no of multiple orgs*" and "*we don't want to compute those property again and again as it is costly operation*" and "*this cache variable will be passed in the multiple orgs*" and "*in dosomething method I want to check whether the cache is being set or not by any other org and if the key is present I will not compute operation and I will just return from cache*". Please, see https://xyproblem.info and https://en.wikipedia.org/wiki/XY_problem –  Jan 27 '21 at 08:39
  • 2
    If you omit the the `ref` keyword, what you give to the ctor _is_ a reference to the `cache` instance. The reference _itself_ will be a copy, but still reference the _same_ instance. If you then change _properties_ of said instance, it _will_ reflect through all other references to the same _instance_. – Fildor Jan 27 '21 at 08:42

1 Answers1

2

If you omit the ref keyword, what you give to the constructor is a reference to the cache instance. The reference itself will be a copy, but still reference the same instance. If you then change properties of said instance, it will reflect through all other references to the same instance.

Consider this example:

using System;
                    
public class Program
{
    public static void Main()
    {
        MyCache sharedCache = new MyCache();
        Department dpt1 = new Department(sharedCache);
        Department dpt2 = new Department(sharedCache);
        
        Console.WriteLine($"Dpt1: {dpt1.CacheValue}");
        Console.WriteLine($"Dpt2: {dpt2.CacheValue}");
        
        sharedCache.Value = 1;
        Console.WriteLine($"Dpt1: {dpt1.CacheValue}");
        Console.WriteLine($"Dpt2: {dpt2.CacheValue}");
        
        dpt1.ChangeValue(2);
        Console.WriteLine($"Dpt1: {dpt1.CacheValue}");
        Console.WriteLine($"Dpt2: {dpt2.CacheValue}");
    }
}

public class Department
{
    private readonly MyCache cache;
    
    public Department(MyCache cache)
    {
        this.cache = cache;
    }
    
    public int CacheValue => this.cache.Value;
    public void ChangeValue(int newValue)
    {
        this.cache.Value = newValue;
    }
}

public class MyCache
{
    public int Value {get; set;} = default;
}

Output:

Dpt1: 0
Dpt2: 0
Dpt1: 1
Dpt2: 1
Dpt1: 2
Dpt2: 2
Fildor
  • 14,510
  • 4
  • 35
  • 67