In a attempt to put some more oop in a program i am looking to make a private instance variable in one class (object) accesable to a class.
private byte [][] J;
All those code refers to this jagged array with this.
Now in the other class i putted all the for loops along with the consolewritlines to display the wanted results. Basicly it says "the name J does not exist in the current context"
But how exactly do i make this J accesable?
I have tried with get and set but i keep getting 'cannot convert to byte to byte[][]'
Also what kind of cyntax would i need with get and set?
Something along like this? Or would i need several more steps? :
public Byte JArray
get { return J; } //can converrt to byte here
set { J = value; } //cannnot convert to byte here
Kind regards
If you want to expose a variable via a property, the type of the property has to be the same as the type of the variable (or compatible):
public byte[][] JArray
{
get { return J; }
set { J = value; }
}
However, you probably don't really need the setter - unless you actually want callers to be able to change J to refer to a different jagged array. Just with a getter they can still change values within the array, but they can't change the variable itself.
Even with this though, callers could still change the contents of the "outer" array, changing a whole "column" at a time:
foo.JArray[10] = new byte[10];
An alternative is to add an indexer to your class:
public byte this[int x, int y]
{
get { return J[x][y]; }
set { J[x][y] = value; }
}
This will only let callers access the actual elements, hiding the fact that it's backed by an array.
Exposing an array directly is generally a bad idea - indeed, leading minds consider arrays to be somewhat harmful.
If I understand the situation correctly, the problem is that your types are mismatched.
Since the variable's type is byte[][] (i.e., an array of arrays of bytes) your property's return type needs to be byte[][]. Currently it's Byte.
That's because the types of your private variable and the public property are not the same. Try this:
public byte[][] JArray
{
get { return J; }
set { J = value; }
}
Or even shorter using automatic properties:
public byte[][] JArray { get; set; }
if J is of type byte[][], the associate property should also be of type byte[][].
Related
In C#, is there a way to keep a reference as a member variable in an object (like an object pointer in C++), not just as a parameter?
EDIT: How can I make a pointer or reference to an object as a member variable?
No. Don't forget that the argument could reference a local variable which is out of scope by the time you use the object later on. A couple of options:
Use a mutable wrapper type
Use a delegate which captures the variable instead
Redesign your code to not require this in the first place
It's hard to know which is most suitable without knowing more about what you're trying to achieve, but ref is a dead-end.
If you mean ref the argument passing convention, then no, you cannot store this. From the first note on MSDN:
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same...
Edit: based on your updated question, C# has different nomenclature about pointers and references. A pointer in C# is an unsafe construct used to somewhat directly reference the memory location of an object. I say somewhat because the memory location can change based on garbage collection (unless you fix it in memory).
References in C# are the default way reference types are passed and stored. They are akin to pointers in other languages, but not quite the same. However, the by-reference argument passing convention allows you to directly change what an object refers to.
If your objective is to keep a mutable reference to a non-reference type local variable, you'll have to encapsulate the local variable in a reference type (like a class). If you could give some sample code, we can give some specific examples.
Yes if it is a reference-type instance. And then it is the only way to store it in another class:
class Bar { }
class Foo
{
private Bar b; // b is a reference to a Bar
}
No if it's about a value-type, or a reference to a reference.
You would see simple object-references everywhere that C++ uses pointers, like in building Trees or Linked-Lists.
class Element { ...; private Element _next; }
For what its worth, you could use an array of size 1 as a reference/pointer. This yields more readable code than creating a new class to wrap a single value type member.
public struct StructWithReferenceMember
{
private int[] intStoredAsReference;
public StructWithReferenceMember(int asValue, int asReference)
: this()
{
IntStoredAsValue = asValue;
intStoredAsReference = new int[] { asReference };
}
public int IntStoredAsValue { get; set; }
public int IntStoredAsReference
{
get { return intStoredAsReference[0]; }
set { intStoredAsReference[0] = value; }
}
}
A similar trick can be used to attempt the highly discouraged practice of using mutable structs.
public class ReferenceProperty<T>
{
private T[] typeReference;
public ReferenceProperty(T value)
{
typeReference = new T[] { value };
}
public T PropertyAsValue
{
get { return typeReference[0]; }
set { typeReference[0] = value; }
}
public T[] PropertyAsReference
{
get { return typeReference; }
}
}
Then use array notation to "dereference" it.
public struct MutableStruct
{
public int member;
public MutableStruct(int value)
{
member = value;
}
}
ReferenceProperty<MutableStruct> referenceToValueType = new ReferenceProperty<MutableStruct>(new MutableStruct(3));
Console.WriteLine("original value: " + referenceToValueType.PropertyAsValue.member.ToString());
//referenceToValueType.PropertyAsValue.member = 4; // compiler error - cannot modify return value because it is not a variable
MutableStruct copyOfStruct = referenceToValueType.PropertyAsReference[0]; // or referenceToValueType.PropertyAsValue
copyOfStruct.member = 4;
Console.WriteLine("original value after modifying copy: " + referenceToValueType.PropertyAsValue.member.ToString());
referenceToValueType.PropertyAsReference[0].member = 5;
Console.WriteLine("original value after modifying reference: " + referenceToValueType.PropertyAsValue.member.ToString());
original value: 3
original value after modifying copy: 3
original value after modifying reference: 5
The way to get the address of a variable is the & operator, similar to C++. Again similarly to C++, you can store the address as a pointer:
class Foo
{
object* _objPtr;
Foo(object obj)
{
unsafe
{
_objPtr = &obj;
}
}
}
Note that any code that uses the address-of operator (&) or pointers must be within a method marked unsafe or within an unsafe code block.
This could be useful if you want to increase performance by not doing array bound-checking for example. The downside (besides safety considerations) is that the assembly must be fully-trusted for it to execute.
As pointed out, in C#, you very rarely actually store pointers, instead you store references so the garbage collector can operate properly. Ensure that you really need pointers in your code before using them!
For more info, see: http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx
I started to learn about C# and I usually use C++.
There is a bunch of things that I'm trying to adapt, but std::array seem like impossible...
I just want to run this kind of code:
public struct Foo {};
public struct Test
{
public Foo value[20];
};
I don't want to allocate each time I use this struct and I don't want to use a class ever...
I saw fixed keyword but it works only for basic types...
There is not equivalent to something as simple as std::array?
I can even do that in C.
How would you sove this problem? (Even if it's still dynamically alocated..)
Using a fixed size buffer (fixed) is only possible for primitive types since its use is intended for interop. Array types are reference types, and so they can have dynamic size:
public struct Test
{
public Foo[] value;
}
Note however that copying the struct will only copy the reference, so the arrays will be identical. I suggest you either make the type immutable (by disabling writing to the array), or change struct to class and control cloning explicitly.
There is no such thing as a fixed size by-value array type in C# (although I have proposed it once). The closest thing you can get to it is a value tuple.
So it seems like there is no way to not do something as stupid as dynamically allocate something know at compile time. But that's C# so I just need to... try to close my eyes.
Anyway I did something to solve array alias and fixed array at the same time (I didn't ask about array alias on this question thought).
public abstract
class Array<T>
{
private T[] data;
protected Array(int size) { data = new T[size]; }
public T this[int i]
{
get { return data[i]; }
set { data[i] = value; }
}
};
public Alias : Array<int>
{
static public int Length = 10;
public Area() : base(Length) {}
};
And some people say it's quicker to write code with C#...
If someone have better I'll glady take it!
I have a struct like this:
public struct MapTile
{
public int bgAnimation;
public int bgFrame;
}
But when I loop over it with foreach to change animation frame I can't do it...
Here's the code:
foreach (KeyValuePair<string, MapTile> tile in tilesData)
{
if (tilesData[tile.Key].bgFrame >= tilesData[tile.Key].bgAnimation)
{
tilesData[tile.Key].bgFrame = 0;
}
else
{
tilesData[tile.Key].bgFrame++;
}
}
It gives me compile arror:
Error 1 Cannot modify the return value of 'System.Collections.Generic.Dictionary<string,Warudo.MapTile>.this[string]' because it is not a variable
Error 2 Cannot modify the return value of 'System.Collections.Generic.Dictionary<string,Warudo.MapTile>.this[string]' because it is not a variable
Why can't I change a value inside a struct which is inside a dictionary?
The indexer will return a copy of the value. Making a change to that copy won't do anything to the value within the dictionary... the compiler is stopping you from writing buggy code. If you want to do modify the value in the dictionary, you'll need to use something like:
// Note: copying the contents to start with as you can't modify a collection
// while iterating over it
foreach (KeyValuePair<string, MapTile> pair in tilesData.ToList())
{
MapTile tile = pair.Value;
tile.bgFrame = tile.bgFrame >= tile.bgAnimation ? 0 : tile.bgFrame + 1;
tilesData[pair.Key] = tile;
}
Note that this is also avoiding doing multiple lookups for no good reason, which your original code was doing.
Personally I'd strongly advise against having a mutable struct to start with, mind you...
Of course, another alternative is to make it a reference type, at which point you could use:
// If MapTile is a reference type...
// No need to copy anything this time; we're not changing the value in the
// dictionary, which is just a reference. Also, we don't care about the
// key this time.
foreach (MapTile tile in tilesData.Values)
{
tile.bgFrame = tile.bgFrame >= tile.bgAnimation ? 0 : tile.bgFrame + 1;
}
tilesData[tile.Key] is not a storage location (i.e., it's not a variable). It's a copy of the instance of MapTile associated with the key tile.Key in the dictionary tilesData. This is what happens with struct. Copies of their instances get passed around and returned everywhere (and is a large part of why mutable struct are considered evil).
What you need to do is:
MapTile tile = tilesData[tile.Key];
if (tile.bgFrame >= tile.bgAnimation)
{
tile.bgFrame = 0;
}
else
{
tile.bgFrame++;
}
tilesData[tile.Key] = tile;
I would suggest creating a utility class:
public class MutableHolder<T>
{
public T Value;
public MutableHolder(T value)
{
this.Value = value;
}
}
Then store a newly-created MutableHolder<MapTile> into each dictionary slot rather than storing a MapTile directly. This will allow you to easily update the map tile associated with any particular key, without having to modify the dictionary itself (an act which would otherwise, at minimum, invalidate the enumerator used by your foreach loop).
Since C# 9.0, you can use the with syntax to create a new copy of the old struct overriding arbitrary fields.
mapTile = mapTile with { bgAnimation = 1 };
Chance struct to Class
before:
public struct MapTile
{
public int bgAnimation;
public int bgFrame;
}
after:
public Class MapTile
{
public int bgAnimation;
public int bgFrame;
}
Hi i am having two classes as below. in our application we will not store data in the array we will be storing in a separate big string and we will be reading from there but while setting and getting the value to array i need the index so that i can take sub string using the index.
public class ClassA
{
private ClassB[] _classB;
publc ClassB[] classB
{
get
{
return _classB;
}
set
{
_classB=value;
}
}
}
public class ClassB
{
public int x;
}
if i set any value to classB like
classA.classB[10].x=1;
is there any way i can get the current index being set in the set property like 10 as the current index or do i need to use Indexes please help me.
Why not make the property declaration read only (just a "get"), and add a Set method:
public void SetValue( int idx, ClassB value )
{
classB[idx] = value;
}
Of course there are no precondition checks and no exception handling code in my example, but if you need to know the index in the set method, I'd go with something like this.
Why do you want to wrap a simple int in a class?
And why expose a fixed-length array publicly? Why not use an ArrayList or one of the other collections that are built in to in the .NET library?
You cannot get the index while setting the property, if for no other reason than that you aren't setting a property in your example at all. You are getting a property value (the classB array), and then setting the x field of the object in that array's position.
There are alternative syntaxes which might work for you. It depends on what your requirements are. Unfortunately, your question doesn't show how you will use the index, so it's not possible to know what you really need.
One option is to just make a method that does the work:
class ClassA
{
public void SetItemXAt(int index, int value)
{
classB[index].x = value;
}
}
Then you have the index parameter to do with what you want.
A variation on this theme is to implement an indexer property on the type:
class ClassA
{
public int this[int index]
{
get { return classB[index].x; }
set { classB[index].x = value; }
}
}
Again, the index parameter is available to you here to use as you wish.
If neither of the above help, you need to fix the question so that you're clear about what you actually want to do.
In C#, is there a way to keep a reference as a member variable in an object (like an object pointer in C++), not just as a parameter?
EDIT: How can I make a pointer or reference to an object as a member variable?
No. Don't forget that the argument could reference a local variable which is out of scope by the time you use the object later on. A couple of options:
Use a mutable wrapper type
Use a delegate which captures the variable instead
Redesign your code to not require this in the first place
It's hard to know which is most suitable without knowing more about what you're trying to achieve, but ref is a dead-end.
If you mean ref the argument passing convention, then no, you cannot store this. From the first note on MSDN:
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same...
Edit: based on your updated question, C# has different nomenclature about pointers and references. A pointer in C# is an unsafe construct used to somewhat directly reference the memory location of an object. I say somewhat because the memory location can change based on garbage collection (unless you fix it in memory).
References in C# are the default way reference types are passed and stored. They are akin to pointers in other languages, but not quite the same. However, the by-reference argument passing convention allows you to directly change what an object refers to.
If your objective is to keep a mutable reference to a non-reference type local variable, you'll have to encapsulate the local variable in a reference type (like a class). If you could give some sample code, we can give some specific examples.
Yes if it is a reference-type instance. And then it is the only way to store it in another class:
class Bar { }
class Foo
{
private Bar b; // b is a reference to a Bar
}
No if it's about a value-type, or a reference to a reference.
You would see simple object-references everywhere that C++ uses pointers, like in building Trees or Linked-Lists.
class Element { ...; private Element _next; }
For what its worth, you could use an array of size 1 as a reference/pointer. This yields more readable code than creating a new class to wrap a single value type member.
public struct StructWithReferenceMember
{
private int[] intStoredAsReference;
public StructWithReferenceMember(int asValue, int asReference)
: this()
{
IntStoredAsValue = asValue;
intStoredAsReference = new int[] { asReference };
}
public int IntStoredAsValue { get; set; }
public int IntStoredAsReference
{
get { return intStoredAsReference[0]; }
set { intStoredAsReference[0] = value; }
}
}
A similar trick can be used to attempt the highly discouraged practice of using mutable structs.
public class ReferenceProperty<T>
{
private T[] typeReference;
public ReferenceProperty(T value)
{
typeReference = new T[] { value };
}
public T PropertyAsValue
{
get { return typeReference[0]; }
set { typeReference[0] = value; }
}
public T[] PropertyAsReference
{
get { return typeReference; }
}
}
Then use array notation to "dereference" it.
public struct MutableStruct
{
public int member;
public MutableStruct(int value)
{
member = value;
}
}
ReferenceProperty<MutableStruct> referenceToValueType = new ReferenceProperty<MutableStruct>(new MutableStruct(3));
Console.WriteLine("original value: " + referenceToValueType.PropertyAsValue.member.ToString());
//referenceToValueType.PropertyAsValue.member = 4; // compiler error - cannot modify return value because it is not a variable
MutableStruct copyOfStruct = referenceToValueType.PropertyAsReference[0]; // or referenceToValueType.PropertyAsValue
copyOfStruct.member = 4;
Console.WriteLine("original value after modifying copy: " + referenceToValueType.PropertyAsValue.member.ToString());
referenceToValueType.PropertyAsReference[0].member = 5;
Console.WriteLine("original value after modifying reference: " + referenceToValueType.PropertyAsValue.member.ToString());
original value: 3
original value after modifying copy: 3
original value after modifying reference: 5
The way to get the address of a variable is the & operator, similar to C++. Again similarly to C++, you can store the address as a pointer:
class Foo
{
object* _objPtr;
Foo(object obj)
{
unsafe
{
_objPtr = &obj;
}
}
}
Note that any code that uses the address-of operator (&) or pointers must be within a method marked unsafe or within an unsafe code block.
This could be useful if you want to increase performance by not doing array bound-checking for example. The downside (besides safety considerations) is that the assembly must be fully-trusted for it to execute.
As pointed out, in C#, you very rarely actually store pointers, instead you store references so the garbage collector can operate properly. Ensure that you really need pointers in your code before using them!
For more info, see: http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx