0

Just want to get some advice on what is the best practice to share a struct.

I have a number of internal classes that I would like to use the same instance of a struct. Instead of passing struct as a param is there an alternative?

Thanks in advance.

Kirk Broadhurst
  • 27,836
  • 16
  • 104
  • 169
nixgadget
  • 6,983
  • 16
  • 70
  • 103
  • 4
    Structs don't have instances. You probably shouldn't be using a struct. – SLaks Oct 12 '11 at 02:13
  • ok then a class it is. thanks ;) – nixgadget Oct 12 '11 at 02:15
  • Parameter passing of some form is necessary to avoid globals (and globals should typically be avoided). – Corbin Oct 12 '11 at 02:18
  • Good, now make that class a singleton, and everything will be able to access the same instance without passing it around as a parameter. – slugster Oct 12 '11 at 02:19
  • A singleton is a glorified global. Singletons should typically be avoided unless there is a situation in which you really do only want one of something (and even then, it's typically better to still pass it around). – Corbin Oct 12 '11 at 02:20
  • http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil – SLaks Oct 12 '11 at 02:22
  • @SLaks - Can you please tell me how to call it when you define a new *** of a struct? Even in the language specification, i find multiple statements like: "...namely the field I in the struct instance given by E...". Do you mean structs can't have managed references pointing towards it? – Polity Oct 12 '11 at 02:25
  • @Polity: Technically, those would be values. What I meant is that structs don't have instances that can be shared (you'll end up copying the values) – SLaks Oct 12 '11 at 02:32
  • You can't have a managed reference pointing _directly_ to a struct; all you can point to is a boxed struct. (or a `TypedReference`) – SLaks Oct 12 '11 at 02:33
  • Heap or Stack? When you call the New operator on a class, it will be allocated on the heap. However, when you instantiate a struct, it gets created on the stack. This will yield performance gains. Also, you will not be dealing with references to an instance of a struct as you would with classes. You will be working directly with the struct instance. Because of this, when passing a struct to a method, it's passed by value instead of as a reference. – nixgadget Oct 12 '11 at 02:34
  • http://msdn.microsoft.com/en-us/library/aa288471(v=vs.71).aspx – nixgadget Oct 12 '11 at 02:35

2 Answers2

2

I think you are asking on how to create a reference or a pointer to a struct. In C# you can do this only with structs made up of only intrinsic value types (int, byte, float, double, char)

Take the following example and compile it with unsafe option

public struct Data
{
    public int id;
    public double x;
}

unsafe class A
{
    Data* data;

    public A(Data* data)
    {
        this.data = data;
    }

    public int ID { get { return data->id; } set { data->id = value; } }
}

unsafe class B
{
    Data* data;

    public B(Data* data)
    {
        this.data = data;
    }

    public double X { get { return data->x; } set { data->x = value; } }
}

unsafe class Program
{
    static void Main(string[] args)
    {
        Data store = new Data();
        A a = new A(&store);
        B b = new B(&store);

        a.ID = 100;
        b.X = 3.33;

        Console.WriteLine("id={0} x={1}", store.id, store.x);
    }
}

It will print out "id=100 x=3.33" even though the value type variable store is never directly assigned those values. Both classes contain a reference to the struct and can manipulate its values.

Want to learn more about pointers to structs, look at this article, or this MSDN document. Yes, the above is legit C# code and despite the unsafe keyword is rather reliable and robust when properly coded. Oh, and it is wicked fast too.

John Alexiou
  • 28,472
  • 11
  • 77
  • 133
1

You should consider using structs only for defining data structures that looks like basic types like strings, int etc..

Those structs are treated as value types in opposition of classes that are treated as reference types.

Mike Verrier
  • 484
  • 2
  • 16