Why does all members of a class show error 'CS0103' - c#

I'm testing a piece of code in c# and vs2022, but I encounter some problems. I try to track the value of some members in a class, but the VS2022 shows error CS0103.
So I would like to know why VS2022 can't show their values because they are certainly in this context.
class Program
{
static void Main(string[] args)
{
ProtoType p = new ProtoType(100, 200);
p.x = 101;
p.y = 20;
int cnt = p.list.Count;
Console.ReadLine();
}
}
class ProtoType
{
public int x = 0;
public int y = 0;
public List<string> list = new List<string>();
public ProtoType(int x, int y)
{
Console.WriteLine("Execute Constructor ProtoType()");
this.x = x;
this.y = y;
}
public ProtoType Clone()
{
Console.WriteLine("Execute ProtoType.Clone()");
return (ProtoType)this.MemberwiseClone();
}
}

Because x, y and list are not variables in this scope. they are members of the class ProtoType. you need to watch for p.x, p.y and p.list in place of the x, y, list.

Related

Initializing obj with/without default values

In c#:
public class SomeClass
{
int x;
int y;
SomeClass (int x, int y)
{
this.x = x;
this.y = y;
}
}
Is there easy way to make new SomeClass without setting x and y instead to
have default values for them and if I set values to set them else to have the
default values?
Sure, with C#6 you can use auto-implemented properties:
public class SomeClass
{
public int X { get; } = 123;
public int Y { get; } = 456;
public SomeClass(){ }
public SomeClass(int x, int y)
{
this.X = x;
this.Y = y;
}
}
Of course you need a parameterless constructor.
If you instead mean default values of the type, that is done automatically(0 for numerical types).
Sure...
new SomeClass(default(int), default(int))
Or, more simply:
new SomeClass(0, 0)
The default value for int is always 0. So even if you define it with a parameterless constructor:
public SomeClass() { }
Those int class members would still default to 0.
You need to define a parameterless constructor:
public class SomeClass
{
int x;
int y;
public SomeClass {}
public SomeClass (int x, int y)
{
this.x = x;
this.y = y;
}
}
When you create an object like:
var someClass = new SomeClass();
both x and y would be initialized using their default values, which is 0.
If you don't want to do so, you could handle this by passing to the constructor that you have already declared the default values of x and y, as already David has pointed out.
Use a parameterless constructor.
Since the instances have to be created somehow using a new keyword, you can use a parameterless constructor inside your class.
public SomeClass ()
{
x = 0;
y = 0;
}
A default constructor would do that automatically.
You can use optional parameters in the constructor.
Read more on named and optional parameters.
public class SomeClass
{
// You can also write this as
// public SomeClass(int x=default(int), int y=default(int)) if you do
// not want to hardcode default parameter value.
public SomeClass(int x=0, int y=0)
{
this.X = x;
this.Y = y;
}
}
You can call it as
void Main()
{
SomeClass a = new SomeClass();
SomeClass b = new SomeClass(1);
SomeClass c = new SomeClass(2,4);
}

C# derived class and base constructor parameter logic

I have a base class:
public class Base
{
public Base(X x ,Y y){
this.x = x;
this.y = y;
}
public X x{get;}
public Y y{get;}
}
and a deriver:
public class Derive : Base
{
public Derive(Z z, Q q) :Base (? ?)
{
}
private void ConstructXY(Z z, Q q)
{
//Advanced logic for creating an X and a Y
if(q.something == 5){
this.x = new X(28);
}
else{
this.x = new X(25);
}
if(this.x.something == 25 && q == 9){
this.y = new Y(1);
}
else{
this.y = new Y(5)
}
}
}
Now I can't correctly call the base constuctor without the "advanced" logic. I used to be able to call ConstructXY() from Derive.ctor() and set x and y from there, this is no longer valid since I removed the x and y setters. My real-life scenario contains a lot more logic so I am not willing to create a ternary mess.
You can call your "advanced" logic if it fits inside a static method
Here is an approach using Tuple available in C# 7 :
public class Base
{
// This constructor was added to avoid calling twice ConstructXY
public Base((X x, Y y) tuple) :
this (tuple.x, tuple.y)
{
}
public Base(X x, Y y)
{
this.x = x;
this.y = y;
}
public X x { get; }
public Y y { get; }
}
public class Derive : Base
{
public Derive(Z z, Q q) : base(ConstructXY(z, q))
{
}
private static (X x, Y y) ConstructXY(Z z, Q q)
{
X x;
Y y;
//Advanced logic for creating an X and a Y
if (q.something == 5)
{
x = new X(5);
}
else
{
x = new X(25);
}
if (x.something == 25 && q == 9)
{
y = new Y(1);
}
else
{
y = new Y(5)
}
return (x, y);
}
}
If you cannot change the access modifiers of X and Y in the base class so they are accessible for subclasses, then you will have to follow the contract, leaving the constructor the only possible place where you can set those members.
The only way to add more logic to calculate those values would be to use static methods, for example like this:
public class Derive : Base
{
public Derive(Z z, Q q)
: base(ConstructX(q), ConstructY(q, z))
{ }
private static X ConstructX(Q q)
{
if (q.something == 5)
return new X(28);
else
return new X(25);
}
private static Y ConstructY(Q q, Z z)
{
if (z.something == 25 && q.something == 9)
return new Y(1);
else
return new Y(5);
}
}
Since these are separate method calls, you cannot calculate both values “at once”, so you cannot make the result of Y depend on the result of X without redoing the calculation based on Z and Q again.
Another way you could solve this is by removing the public constructor on Derive altogether and provide a static factory method instead:
public class Derive : Base
{
private Derive(X x, Y y)
: base(x, y)
{ }
public static Derive Create(Z z, Q q)
{
// here you can use your original logic to calculate X and Y
X x = …
Y y = …
return new Derive(x, y);
}
}
Depending on your complexity of those calculations, this might be the better solution. If you do need the original Z and Q values, just extend the private constructor to also take those and store them as well:
private Derive(Z z, Q q, X x, Y y)
: base(x, y)
{
this.Z = z;
this.Q = q;
}
I don't really like this way of doing it and would avoid it if possible but you can use a ternary statement in your call to base:
public Derive(Z z, Q q)
: base(new X(xCondition ? 28 : 25), new Y(yCondition ? 1 : 5))
Use static methods to do the conversion. Like this.
public class Derive : Base
{
public Derive(Z z, Q q) :base (ConvertToX(z, q), ConvertToY(z, q))
{
}
private static X ConvertToX(Z z, Q q) {
if(q.something == 5){
return new X(28);
}
return new X(25);
}
private static Y ConvertToY(Z z, Q q) {
// TODO
}
}
Why not declare your base class setters as private:
public class Base
{
public Base(X x ,Y y){
this.x = x;
this.y = y;
}
public X x{get; private set;}
public Y y{get; private set;}
}
That way you can still set them in the constructor, and they would not be settable outside?

Calling a parent class from a subclass

class experiment
{
int xCoord = 0;
int yCoord = 0;
public experiment(int x, int y) {
this.xCoord = x;
this.yCoord = y;
}
}
class result :experiment{
int zCoord = 0;
public result(int z) : base(x,y)
{
this.zCoord = z;
}
}
Can anyone help me solve this simple problem. I'm having an error base(x,y) it says the name 'x' does not exists in the current context and also goes for the y.
x and y are local fields to class experiment they are not visible in inherited class, you may call the base constructor with default values like:
public result(int z) : base(0,0)
Also please follow General Naming Conventions from Microsoft, so the class names begins with upper case character.
EDIT:
It would be better if your child class has a constructor to receive parameter x and y, and the it calls the base class constructor with those values like:
public result(int x, int y, int z) : base(x,y)
{
this.zCoord = z;
}
There is no x,y in constructor of result class.
You pass to your constructor z but tell your base constructor to recieve x and y. Though there are no x and y at that time.
Try this:
public result(int z, int x, int y) : base(x,y)
{
this.zCoord = z;
}
Or set fix values (no variables):
public result(int z) : base(0, 0)
{
this.zCoord = z;
}

Manipulating variables in structs in C#

I'm messing around trying to learn C# in Visual Studio. I have only basic coding knowledge, and I bought C# 5.0 in a nutshell. I'm loving the book, and trying to make mini programs out of everything I read to help make it stick. I thought structs were something simple, but for whatever reason I just can't get a struct to work.
So here's a brief and ultra basic example from the book.
public struct Point {
int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
}
Point p1 = new Point();
Point p2 = new Point(1, 1);
It works fine. But now say I want to manipulate the x and y variables in p1 or p2. I've tried so much, and I can't get it to work.
public struct Point {
public int x;
}
Point p1 = new Point();
p1.x = 10;
This won't work. When I try to set p1.x to 10, I get an error. It says p1 is a "field" but is used like a "type."
There's probably something simple I'm missing, but my patience for trial and error has run out. So what am I doing wrong? I understand the basic concept of why a struct is useful, but I need to be able to actually use it once I make it!
Tono Nam's answer is correct but incomplete.
To set the values of x and y the way you want to, you will also need to set the correct access modifier for x and y e.g.
class Program
{
public struct Point
{
public int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
}
static void Main(string[] args)
{
var p1 = new Point();
var p2 = new Point(1, 1);
p1.x = 1;
p1.y = 1;
}
}
You'll want to use public to access x and y from any class.
You'll want to use internal if you only want to access x and y from within the same class where the struct Point is defined.
class Program
{
public struct Point
{
int x, y;
public Point(int x, int y) { this.x = x; this.y = y; }
}
static void Main(string[] args)
{
Point p1 = new Point();
Point p2 = new Point(1, 1);
}
}
Just like #pst mentioned. p1 and p2 need to be inside a method. In this case they are inside the main method.

KeyNotFoundException in filled dictionary

I am trying to modify value in dictionary, but the compiler throws KeyNotFoundException. I'm sure, I declared that key in dictionary, because I am calling GenerateEmptyChunks() method, which fills dictionary with chunks with key of their position and values are empty for level generator. I've checked debugger and Chunks dictionary object is correctly filled with keys and values. Is it caused by my unworking CompareTo method? If yes, how I have modify CompareTo method to return right values?
public Dictionary<WPoint, WChunk> Chunks = new Dictionary<WPoint, WChunk>();
GenerateEmptyChunks() method:
public void GenerateEmptyChunks(int Xcount, int Ycount)
{
for(int x = 0; x <= Xcount; x++)
{
for (int y = 0; y <= Ycount; y++)
{
this.Chunks.Add(new WPoint(x, y), new WChunk(x, y));
}
}
}
AddBlock() method which is called by level generator for each tile:
public void AddBlock(WPoint location, int data)
{
this.Chunks[location.GetChunk()].AddTile(new WTile(location, data));
}
WChunk object:
public class WChunk
{
public int ChunkX;
public int ChunkY;
public SortedDictionary<WPoint, WTile> Tiles = new SortedDictionary<WPoint, WTile>();
public WChunk(int posX, int posY)
{
ChunkX = posX;
ChunkY = posY;
}
public void AddTile(WTile tile)
{
Tiles.Add(tile.GetLocation(), tile);
}
}
WPoint object:
public class WPoint : IComparable
{
public float X;
public float Y;
public WPoint(float x, float y)
{
X = x;
Y = y;
}
public WPoint GetChunk()
{
//Oprava pre bloky mensie ako (1,1)
if (X <= 16 && Y <= 16)
{
return new WPoint(0, 0);
}
else
{
double pX = (double)(X / 16);
double pY = (double)(Y / 16);
return new WPoint((int)Math.Floor(pX), (int)Math.Floor(pY));
}
}
public int CompareTo(object obj)
{
WPoint point2 = (WPoint)obj;
if (point2.X == this.X && point2.Y == this.Y)
{
return 0;
}
else if (point2.X >= this.X && point2.Y >= this.Y)
{
return -1;
}
else
{
return 1;
}
}
}
Any ideas why is compiler rejecting keys, when they are in dictionary?
Yes. You have not overridden GetHashCode.
Dictionary is using the GetHashCode and Equals for key comparisons, so implementing the IComparable interface is not enough. Have a look at this answer, that's exactly what you need.

Categories

Resources