How do I shorten the path to a property? - c#

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.

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;

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.

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)
}

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.

How about:
var shortCut = Object.ObjectTwo;
shortCut.Variable = something;

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);
}

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.

Related

Anonymous type with var gives error CS0825 [duplicate]

This question already has answers here:
Implicit typing; why just local variables?
(6 answers)
Closed 1 year ago.
I want to create an anonymous type in C# inside a class.
The examples I have seen use var to create an anonymous variable
var RecordId = new
{
Foo = 0,
Bar = "can be also a string"
};
However I want to create my anonymous variable inside a class.
public class Logger //: LogBase
{
var RecordId = new
{
Foo = 0,
Bar = 1
};
}
So when Logging I can do:
Logger.RecordId.Foo
But declaring my anonymous type as var triggers the following error:
CS0825: The contextual keyword 'var' may only appear within a local variable declaration.
What is the type of an anonymous variable, so I don't have to use var?
I understand what the error is telling me, but I don't want to move my variable inside a function, it needs to be a property of Logger.
Edit: enum is what I tried t the beginning, but I need the values to be more flexible than just integers (like strings, so I can dump jon files).
I updated my question to reflect that.
var (and by definition anonymous types) can only be declared inside a method, the error message is basically telling you that. If you need this type to be at class level, then make a class/struct/tuple to store it.
public static class Record
{
public static int Foo { get; set; }
public static int Bar { get; set; }
}
public class Logger //: LogBase
{
public static Record RecordId { get; set; } = new Record();
}
Now you can do this:
var foo = Logger.RecordId.Foo;
Note that I also used static so you don't need to create a new instance of the class, but change that if you think it's relevant.
public class Logger //: LogBase
{
public enum RecordId
{
Foo = 0,
Bar = 1
}
}
If you do not want strings you can do the above.
public class LogCategory
{
private LogCategory(string value) { Value = value; }
public string Value { get; private set; }
public static LogCategory Foo { get { return new LogCategory("Foo"); } }
public static LogCategory Bar { get { return new LogCategory("Bar"); } }
}
If you want strings you could create your own class something like the above.
You can use the dynamic type to have an anonymous instance variable.
public class Foo
{
dynamic bar = new {
A = 1,
B = 2
};
public void Print() {
Console.WriteLine(bar.A);
}
}
Try it out!
Just because you can do this doesn't mean it's a good idea. See DavidG's answer for an alternative using a strongly-typed object that will not require you to expose your code to the many problems associated with the dynamic type.

C# referencing a methods variables from another method [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Sometimes it happens that I want to use a lot of Method As variables in Method B.
Usually its quite a pain to pass all the variables to this method, especially if I have to do this a lot of times (but cannot simply copy paste, because some things change) or am just to lazy.
Is there such a thing like a "inner Method"? Or some concept to handle this in an easy way?
What I want to do:
public void A()
{
int a = 4;
string b = "Hello World";
B(ref vals);
//Or like so
C(ref current);
}
public void B(ref AllValues)
{
a = 3;
...
}
public void C(ref MethodThatSharesAllValues method)
{
method.a = 3;
...
}
If they all are in the same class
You can configure them as class variables:
public class MyClass{
//set this as private/protected/public or nothing and you can also set a default value
int a;
public void A()
{
a = 4;
string b = "Hello World";
B();
C();
}
public void B()
{
a = 3;
...
}
public void C()
{
a = 3;
...
}
}
Elseway
public static class MyClassA{
public static int a = 0;
public static void MethodA(){
this.a = 3;
}
}
now from method B you can access MyClassA
int myExValueA = MyClassA.a;
Elseway you gotta pass them as parameters
hope this helps
You can create a class which will hold your parameters and then pass only an instance of this class
public void metA(Parameters input)
{
input.a = 5;
input.c = "hello";
metB(input);
}
public void metB(Parameters input)
{
input.b = 10;
}
public class Parameters
{
public int a;
public int b;
public string c;
}
You can declare the variables static in a class header and use them as you like, private if are in the same class, protected for child classes, internal or public else. Or box the variables in a class like this:
public class Foo
{
public int A { get; set; }
public int B { get; set; }
public string C { get; set; }
}
If passed variables are the same type you can use data structure like int[] or string[] or List<int> or List<string> and pass them without ref but this has the disadvantage that more than often you would not use all varibales from the structure as it is also the case with the class boxing variant.
Something like the following:
public void foo() {
int a = 10;
// ...
}
public void foo_bar() {
// "a" is not in scope for foo_bar, so this won't compile
a = 20;
// ...
}
would definitely be invalid. I don't think that this was what you were driving at in your question though.
You can do something somewhat similar to what you ask for using closures but they're a bit tricky to work with. Basically, something like this would be valid (and I'm not sitting in front of an IDE so forgive me if the syntax is a little off):
Func<int> GetCounter() {
int count = 0;
// This will capture the count variable from its context
Func<int> method = () => ++count;
return method;
}
While a fair number of languages (including some versions of C++ now I guess) have closures (or some similar variant), there seems to be little consistency in exactly how they work across languages (e.g. on whether the "count" variable should be immutable once it's captured) so it's important to check the documentation for the language you're using (in this case, C#) to understand exactly how they work.
In terms of the first code sample I provide, I doubt that that's what you were asking about, but just as a brief digression you probably wouldn't really want it to be the allowable anyway (and again I suspect that this isn't the syntax/semantics you're asking about) as it would quickly lead to unexpected/undefined behavior. For example:
If you have a local variable a that's initialized in Foo() and you refer to it in Foo_Bar() before you run Foo(), what should its value be?
If you run Foo() to initialize the variable, edit the variable in Foo_Bar(), and then run Foo() again, should you re-initialize the variable or allow it to remain what Foo_Bar() set it to?
Is it safe to garbage collect a local variable after the method call completes, or might it be referred to again?
See the following:
public class SomeObject
{
public int SomeProperty { get; set; } = 6;
// ...
}
public class SomeOtherObject
{
// ..
}
void foo() {
// What is the content of "a" before foo() runs?
object a = new SomeObject();
// Which "a" should this refer to - the one in foo() or the one in foo_bar()?
// Also, is this a valid cast given that we haven't specified that SomeOtherObject can be cast to SomeObject?
var b = (SomeObject)a;
// If we run foo() again, should "b" retain the value of SetProperty or set it back to the initial value (6)?
b.SetProperty = 10;
// ...
// Is it safe to garbage collect "a" at this point (or will foo_bar refer to it)?
}
void foo_bar() {
object a = new SomeOtherObject();
// ...
}

Change an item property received from a linq query

I need to change the value of an item of a list returned by a query... It must be simple, but i can´t see it using linq.
The list is composed by elements of this structure:
public struct HeaderButton
{
public string content {get; set;}
public BitmapImage icon {get; set;}
public PageContainerFactory.ContainerType containerType {get; set;}
public bool IsSelected { get; set; }
}
private List<HeaderButton> _headerButtons;
public List<HeaderButton> HeaderButtons
{
get
{
if (_headerButtons == null)
_headerButtons = new List<HeaderButton>();
return _headerButtons;
}
set { _headerButtons = value; }
}
I´ve tried this:
HeaderButtons.First(x => x.containerType == CurrentContainer.CType).IsSelected = true;
And the compiler tells me:
Cannot modify the return value of 'System.Linq.Enumerable.First(System.Collections.Generic.IEnumerable, System.Func)' because it is not a variable
And now the query that i´m trying:
var h = HeaderButtons.First(x => x.containerType == CurrentContainer.CType);
h.IsSelected = true;
I had to take the element in a var because of the compiler error. And doing it as represented in the code above, obviously "h" does not points to the "HeaderButtons" real element since it is a new HeaderButton object and not a reference.
Following your comments, i decided to make a nested class in place of the structure since this kind of objects are not used outside of the content class, and now that is a class (object reference) and not a struct (value), everything works fine.
The code:
sealed class MainViewModel : ViewModelNavigator
{
internal class HeaderButton
{
public string Content { get; set; }
public BitmapImage Icon { get; set; }
public PageContainerFactory.ContainerType ContainerType { get; set; }
public bool IsSelected { get; set; }
}
...
private List<HeaderButton> _headerButtons;
public List<HeaderButton> HeaderButtons
{
get
{
if (_headerButtons == null)
_headerButtons = new List<HeaderButton>();
return _headerButtons;
}
set { _headerButtons = value; }
}
...
HeaderButtons.First(x => x.ContainerType == CurrentContainer.CType).IsSelected = true;
The compiler is saving you from shooting yourself in the foot.
Because HeaderButton is a struct it is passed by value instead of by reference. Which means that the Linq First operator is acting on (and will return) a value copy of the element in the list.
Because the return value from First is not assigned to anything it is temporary and will go out of scope at the end of the statement, and what's more since it is a value copy and not a reference to the item in the list any changes you make to it will not affect the item in the list anyway.
If this were to compile you might easily be misled to thinking that you had updated the item in the list, which you would not have. By refusing to compile the compiler is saving you from having to track down what could be a tricky bug to find.
If you have reason to keep HeaderButton as a struct then a statement like this will enable you to update it.
var hb = HeaderButtons.First(x => x.containerType == CurrentContainer.CType);
HeaderButtons[HeaderButtons.IndexOf(hb)].IsSelected = true;
If you go this route you need to ensure your struct's equality operations behave in a way that is useful to you, which hinges on the same factors as 'If you have reason to keep HeaderButton as a struct' because part of wanting to use a struct instead of a class means wanting value equality instead of reference equality semantics.

How do I call a getter or setter in C#

I understand how to create a getters and setters
public myClass
{
public int myVal { get; set; }
// more stuff
}
but I don't understand how to call it later on.
public myOtherClass
{
public myOtherClass()
{
myClass localMyClass = new myClass();
localMyClass.???set??? = 42;
// Intelisense doesn't seem to give any obvious options after I enter
// the period.
}
}
How should I set the value of myVal in localMyClass?
localMyClass.myVal = 42;
Getters and setters let you treat the values like public properties. The difference is, you can do whatever you want inside the functions that do the getting and setting.
Examples:
store other variables
private int _myVal, myOtherVal;
public int MyVal { get; set { _myVal = value; myOtherVal++; } }
make numbers up / return constants
public int MyVal { get { return 99; } set; }
throw away the setter
private int _myVal;
public int MyVal { get { return _myVal; } set { ; } }
In each of these cases, the user will feel like it's just a public data member, and simply type
localMyClass.myVal = 42;
int i = localMyClass.myVal;
The gettors and settors let you make an implementation of your own. Also, as Hogan says, "There are a number of libraries and add-ons [e.g. MVC.NET] that require you to use getter and setter functions" - even if it's for the trivial {get; set;} case.
Set:
localMyClass.myVal = 42
Get:
int variable = localMyClass.myVal;
From the outside, the syntax for accessing getters and setters is indistinguishable from that of accessing variables. Assignments translate into calls of setters, while plain expression uses translate into calls of getters.
In intellisense, the list of getters and setters should open upon placing a dot . after the variable name. Properties should have blue markers to the left of them (as opposed to magenta-colored markers to the left of methods).
You want this
localMyClass.myVal = 42;
to call the setter
and this
varName = localMyClass.myVal;
to call the getter.
Get: var tmp = localMyClass.myVal;
Set: localMyClass.myVal = 2;

C# set/get shorthand Question

I"m a little confused with this short hand. Does this allow me to acesss myVar and set myVar like so?
object.myVar = 5;
newNum = object.myVar;
I don't get this.
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
No, what this means is that you have a "hidden" private integer called myVar that nobody outside the class can see, but people from the outside can only see a property called MyProperty, that happens to redirect to myVar, but they won't know it !
from the inside, you can do :
this.myVar = 12;
int test = this.myVar; /*(this. would actually be optionnal)*/
from the outside, if myInstance is an instance of your class, people can do this :
int test = myInstance.MyProperty;
myInstance.MyProperty = 12;
The point of properties is to hide the private members, and control how they are accessed.
It does not allow you, that is the point. You access the private variable via the public property.
In version 3.0 and above you can also do:
public int MyProperty { get; set; }
And access them like so:
object.MyProperty = 5;
newNum = object.MyProperty;
No it won't be redundant
public int MyProperty { get; set;}
This creates a public and a private variable.
Outside classes can command it but there is a hidden private variable that will use the get set method. This is still safe since it is the class itself that will change the values and not some other method from outside.
No it allows you to access your variable myVar by using this:
object.MyProperty = 5;
newNum = object.MyProperty;
you could get rid of the backing variable entirely and do this though:
public int MyProperty
{
get; set;
}
which will still allow you to access your property like the first code section in my answer.
public int MyProperty { get; set; }
wouldn't this be redundant since if MyProperty is public it can already be 'get' and 'set'?

Categories

Resources