5

For example if I have Object.ObjectTwo.Property and I don't want to clutter my code by writing that all the time, is there a way to make it shorter?

Instead of writing Object.ObjectTwo.Property = something, I would like to be able to write myVariable = something.

I couldn't find anything when I tried searching.

Edit: The member in question is a property.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
Mawkey
  • 53
  • 5
  • Maybe just declare a separate variable? ObjectA=Object.ObjectTwo.Variable – Russ J Feb 15 '19 at 14:27
  • 5
    **Is Object.ObjectTwo.Variable actually a variable**? This is important. C# 7 allows you to make short aliases for *variables*, but not for *properties*. Local variables, formal parameters, array elements, instance fields, static fields and unsafe pointer dereferences are *variables*. Properties are not. Which is it? Is `Variable` a field, or a property? – Eric Lippert Feb 15 '19 at 15:23
  • 3
    Second question, are `Object` and `ObjectTwo` of *reference type* or *value type*? – Eric Lippert Feb 15 '19 at 15:26
  • 2
    Also FYI pretty much none of the answers, including the one you marked as correct, are correct. **There is not enough information in the problem yet to answer the question definitively and marking it as answered was premature**. – Eric Lippert Feb 15 '19 at 15:28
  • It is a property! – Mawkey Feb 15 '19 at 16:38
  • I was working with Unity. I was working with a line looking like this: camera.backgroundColor.r = 1 and I wanted it to be shortened to bgColor = 1. Where camera is a class, backgroundColor is a struct and r is a float. – Mawkey Feb 15 '19 at 16:56
  • Is *backgroundColor* a property or a variable? Presumably it is a variable, since the code given would not work if it were a property and the value is a struct, since the mutation would be lost. More generally though, mutating a value type like this is considered a poor practice. As this question has aptly pointed out, the semantics of mutating values of struct-valued fields is very tricky! – Eric Lippert Feb 15 '19 at 23:35

7 Answers7

4

In C#, you can create shorthands for variable types at the global scope (where you put statements like using System;).

If you want to shorten Object.ObjectTwo to something simpler, you can use a using statement in the following manner:

using Object.ObjectTwo = ObjTwo;

Then, you can later call ObjTwo.Variable = someVar;, and it will act as if you had used Object.ObjectTwo.Variable = someVar;

absoluteAquarian
  • 510
  • 3
  • 12
3

Maybe just declare a separate variable?

var ObjectA = Object.ObjectTwo.Variable;

Though while this is more convenient for you, on the computer side, it is one more declared variable.

meJustAndrew
  • 6,011
  • 8
  • 50
  • 76
Russ J
  • 828
  • 5
  • 12
  • 24
  • Would this actually change the original value if I went ObjectA = something? Or is this just manipulating a copy of the original? – Mawkey Feb 15 '19 at 14:42
  • Nope, you’re just copying the value into the new variable. As I mentioned, the trade off for easier code for you here is that you will have one more variable on your memory. Only you will know if that matters or not. – Russ J Feb 15 '19 at 14:47
  • 1
    This applies only to the case where inside Object.ObjectTwo.Variable, Variable is a reference type. If it is a value type it does not solve the problem. – Zack ISSOIR Feb 15 '19 at 14:49
  • Hm... It's not exactly what I would've hoped for but because none else seems to have a better answer I will mark this as answer. Thanks for the help everyone! – Mawkey Feb 15 '19 at 14:59
3

In C# 7, you can use Ref Locals. Unlike most other approaches, this approach can be used safely even when operating on structs.

This approach is only available on fields. Properties cannot be aliased using ref.

Below is an example.

struct bar
{
    public int myprop;
}

struct bash 
{
    public bar mybar;
}

void Main()
{
    bash bash1 = new bash();
    bash1.mybar.myprop = 1;
    Console.WriteLine(bash1.mybar.myprop); //Outputs 1 (Direct access)

    bar bar2 = bash1.mybar;
    bar2.myprop = 2;
    Console.WriteLine(bash1.mybar.myprop); //Outputs 1 (Bug: access via a copy)

    ref bar bar3 = ref bash1.mybar;
    bar3.myprop = 3;
    Console.WriteLine(bash1.mybar.myprop); //Outputs 3 (Ref Local)

    bar3 = new bar();
    bar3.myprop = 4;
    Console.WriteLine(bash1.mybar.myprop); //Outputs 4 (Ref local with assignment)
}
Brian
  • 25,523
  • 18
  • 82
  • 173
2

You can give yourself some syntactic sugar by implementing "shortcuts" that might get you closer to your goal.

public class ObjectOne
{
    public ObjectTwo ObjectTwo {get;set;}

    public VariableType Var {get{return ObjectTwo.Variable;}}
}

This allows you to write for example:

var one = new ObjectOne();

one.Var = something;

@Eric Lippert is right, this is only one possible solution the Question needs more information to be answered correctly.

mxmissile
  • 11,464
  • 3
  • 53
  • 79
  • Eric Lippert provides a generic implementation of such a short-cut class [here](https://stackoverflow.com/a/2982037/18192). – Brian Feb 15 '19 at 17:01
0

How about:

var shortCut = Object.ObjectTwo;    
shortCut.Variable  = something;
Murray Foxcroft
  • 12,785
  • 7
  • 58
  • 86
0

The example camera.backgroundColor.r = 1 from the comment simply won't work. You will get the following error

Cannot modify the return value of 'Camera.backgroundColor' because it is not a variable

and the reason has been discussed here. The point is that in Unity the Camera itself is the class but the Color (the type of the backgoundColor) is mutable struct, be careful though they are evil.


When you assign a new value to a variable of a value type, that value is copied. When you assign a new value to a variable of a reference type, the reference is copied, not the object itself

public class Camera
{
    public BackgroundColorValue backgroundColorValue { get; set; } 
        = new BackgroundColorValue();
    public BackgroundColorRef backgroundColorRef { get; set; } 
        = new BackgroundColorRef();
}

public struct BackgroundColorValue
{
    public int r { get; set; }
    public int g { get; set; }
    public int b { get; set; }
}

public class BackgroundColorRef
{
    public int r { get; set; }
    public int g { get; set; }
    public int b { get; set; }
}

var shortCutValue = cammera.backgroundColorValue;
var shortCutRef = cammera.backgroundColorRef;

shortCutValue.r = 5;
shortCutRef.r = 10;

//cammera.backgroundColorValue.r == 0, shortCutValue == 5
//cammera.backgroundColorRef.r == 10, shortCutValue == 10

The value types are copied by value so shortCutValue doesn't have any connection with the camera.backgroundColor.r except they have the same value in one period of their existance. On the other hand, shortCutRef is an actual shortcut and it will work until you change the reference to the backgroundColorRef which might be possible if Camera is mutable.

var shortCutRef = cammera.backgroundColorRef;
camera.backgroundColorRef = new BackgroundColorRef(); //link to shortcut broken
shortCutRef.r = 10;

//cammera.backgroundColorRef.r == 0, shortCutValue == 10

I am not sure if this is applicable in general, there might be some case Eric knows, but if you have A.B.C.D....N.r you could make a shortcut if N is actually reference type and to be sure the link with the shortcut will be unbreakable all types from N to A should be immutable. Otherwise, you could break a link somewhere.

Johnny
  • 8,939
  • 2
  • 28
  • 33
0

Use a local function (or on C# versions < 7.0 a delegate).

public void DoWork(SomeType thing, PropertyType value1, PropertyType value2)
{
    void Shortcut(PropertyType value) => thing.ThingTwo.Property = value;

    Shortcut(value1);
    Shortcut(value2);
}
Dave M
  • 2,863
  • 1
  • 22
  • 17