I am working on a learning project in which I am trying to learn better practices. I have a class, Player, the Player among other things has Dictionary called Items, where items can be stored. The Player is initialized with just a Name and an Age, the Dictionary is supposed to be empty at the initialization of the Player.
Alongside the story, the Player can get items which will be stored in the inventory, so I am trying to create a method that can be called to do this, however I face the following issue:
If the method is not static, it cannot be called from outside the class with the following error:
An object reference is required for the non-static field, method, or property 'Player.AddItems(int, string)'.
If the method is static, it does not see the Items Dictionar with the following error:
An object reference is required for the non-static field, method, or property 'Player.Items'.
I am trying to call it from the main function (will become a class later) with:
Player.AddItems(0, "Wallet");.
Any suggestions are appreciated.
class Player
{
public string Name { get; set; }
public int Age { get; set; }
public Dictionary<int, string> Items { get; set; }
public float Damage { get; set; }
public float Health { get; set; }
public Player(string Name, int Age)
{
this.Name = Name;
this.Age = Age;
this.Items = new Dictionary<int, string>();
this.Damage = 0;
this.Health = 20;
}
public void AddItems(int key, string item)
{
this.Items.Add(key, item);
}
}
An object reference is required for the non-static field, method, or
property 'Player.AddItems(int, string)'
You need to create an object first to call a non-static method of a class.
Player p = new Player("John", "25");
p.AddItems(1, "Data");
An object reference is required for the non-static field, method, or
property 'Player.Items'.
You can't access non-static members from static methods
PS: You can assign default values to properties directly.
class Player
{
public Player(string Name, int Age) : this()
{
this.Name = Name;
this.Age = Age;
}
public string Name { get; set; }
public int Age { get; set; }
public Dictionary<int, string> Items { get; set; } = new Dictionary<int, string>();
public float Health { get; set; } = 20;
public float Damage { get; set; }
public void AddItems(int key, string item)
{
this.Items.Add(key, item);
}
}
Related
Is there any way to auto generate a constructor which looks like this:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public User(int id, string name)
{
Id = 0;
Name = "";
}
}
Currently I am creating a constructor like that with the refactoring tool (CTRL + .):
public User(int id, string name)
{
Id = id;
Name = name;
}
and editing each line afterwards which is pretty cumbersome when you have 20 properties per class. Is there a better way to that?
(Maybe to define a code snippet, so that we can somehow read the class properties with reflection and define them as snippet parameters?)
If you have a class with 20 properties, why do you need a constructor with 20 parameters? Maybe have a sense, but I usually create constructors to initialize properties that are relevant, to simplify the code, not to set all properties.
For your class, you can set the default values when you define the property and all constructors will use this values as the default.
public class User
{
public int Id { get; set; } = 0;
public string Name { get; set; } = string.Empty;
// Here you can even omit the constructor
public User()
{
}
}
Another thing that maybe useful is define a constructor with X parameters and reuse this constructor in other constructors with less parameters:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public User()
: this(0, string.Empty)
{
}
public User(int id, string name)
{
Id = id;
Name = name;
}
}
You can replace this(0, string.Empty) for this(default, default) if you want use the default value of each type.
If you need object create with default value for properties. You can code like this:
public class User
{
public int Id { get; set; } = 0;
public string Name { get; set; } = "";
}
Purpose of quick action "generate constructor" make method contructor for assign value to fields or properties. Don't use it in the case of just assigning default values.
do you mean initialize properties? Initializing properties through the code reflection mechanism also requires one-by-one assignments. For private object properties, it is necessary to de-private encapsulation. The operation of initializing properties in c# is generally to initialize object properties or object initializers in the form of constructors. Thank you hope it helps you
class Program
{
static void Main(string[] args)
{
Student student = new Student()
{
age = 25,
name = "java",
sex = "female"
};
}
class Student
{
public int age { get; set; }
public string name { get; set; }
public string sex { get; set; }
public Student()
{
}
public Student(int age, string name,string sex)
{
this.age = age;
this.name = name;
this.sex = sex;
}
}
}
What does private access modifier for init only setter in C# mean? I usually make setter as private for most of the properties in my domain classes. With init, does it matter?
The following seem to work without any problem, the compiler does not complain.
public class Point
{
public int X { get; private init; }
public int Y { get; private init; }
}
So how is the above different from the below. There is not private below.
public class Point
{
public int X { get; init; }
public int Y { get; init; }
}
It affects where the setter can be called from, just like normal setters.
Consider this code:
public class Point
{
public int X { get; private init; }
public int Y { get; private init; }
}
class Program
{
static void Main()
{
var point = new Point { X = 10, Y = 20 };
}
}
That fails with two compile-time errors:
The property or indexer 'Point.X' cannot be used in this context because the set accessor is inaccessible
(and the equivalent for Y).
The same initializer would be valid in the Point class, because the set accessors are accessible there. For example, you might want to use a public factory method, which is implemented with an object initializer:
public class Point
{
public int X { get; private init; }
public int Y { get; private init; }
public static Point FromXY(int x, int y) =>
new Point { X = x, Y = y };
}
(There are various reasons why that might not be ideal, or you might prefer to add parameters to a private constructor, but it's an example of where the private init-only setters are accessible.)
Likewise the code above would be valid without the private part of the set accessors, because then they can be called from anywhere (as part of an object initializer).
The init keyword was added in c# 9.0 in order to add immutable properties on objects.
The problem we used to have is that if you have this object you could still modify the Name property (although it has a private setter) via a public method. for example:
public class Person
{
public Person(string name)
{
this.Name = name;
}
public void SetName(string name)
{
this.Name = name;
}
public string Name { get; private set; }
}
And we also couldn't use object initializers
var person = new Person
{
Name = "Jane Doe" // Compile Error
};
Now, if we change the code to use init
public class Person
{
public Person(string name)
{
this.Name = name;
}
public string Name { get; init; }
}
We are now able to use object initializers
var person = new Person
{
Name = "Jane Doe" // No error
};
But, if we use your private init like your example
public class Person
{
public Person(string name)
{
this.Name = name;
}
public string Name { get; private init; }
}
We won't be able to use object initializers
var person = new Person
{
Name = "Jane Doe" // Compile error
};
I am busy with a really small console application for c#. I am just new into c# and i'm only familiar with Java. My school gave the assignment to create a console application that simulates a car dealer. I already wrote a bunch of code to add cars by console. Things like brand and type and max speed are already implemented. The only thing i still need to realize is the auto creation and incremental of an ID for a car. It has the be unique of course.
My first approach was making the id field static and increment it in the constructor so that each time the object gets created the id gets ++;
I saw allot of people on stackoverflow doing allot of things but the solutions did not work or the where to big.
This is my code;
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public static int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID++;
}
}
I added 3 cars to my list but the result is that all cars have ID 3;
Maybe someone could help me, thanks in advance.
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; private set; }
public static int globalCarID;
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID = Interlocked.Increment(ref globalCarID);
}
}
This maintains a global ID counter, and increments it atomically to make it thread-safe.
Note that the first ID assigned this way would be 1. You can initialize globalCarID with -1 to start at 0.
Just to remove static and add lock section for avoiding duplicate of Ids
class Car : Vehicle
{
private static object sync = new object();
private static int _globalCount;
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
lock (sync)
{
this.carID = ++globalCount;
}
}
}
A static variable is shared between all instances of the class.
Incrementing it in the constructor makes all instances of that class 'see' the last value assigned to the static variable.
You should create a normal instance carID variable (not static) and use a protected static variable defined in the base class to grab the current value at constructor time, assign to your carID instance variable and then increment the base class value.
class Vehicle
{
protected static int FakeID = 1;
}
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID = base.FakeID++;;
}
}
void Main()
{
Car a = new Car("xyz", "Auto", 120, 12000);
Car b = new Car("kwx", "Moto", 180, 8000);
Console.WriteLine(a.carID);
Console.WriteLine(b.carID);
}
Keep in mind that this will work correctly if your code doesn't use multithreaded access to the constructor. In case of multithreading you need to look at Interlocked.Increment
I've created a generic search parameter class for reuse in several libraries (see below). I'm trying to find a better way to implement the list of values for each parameter. I will be passing a list of the parameters to a method but varying types for the values for each parameter. I've implemented it as simply type object and will convert to the correct type as necessary in my code, but I feel like there is probably a better way to do this and I'm not coming up with much. Anyone done anything similar or have a suggestion? Thanks!
Generic Abstract Class:
public class SearchParameter<T>
{
public T Name { get; set; }
public List<object> Values { get; set; }
}
Inheriting Class:
public enum OrderSearchParameterNames
{
Barcode,
DateCompleted,
DatePlaced,
OrderStatus,
UserId
}
public class OrderSearchParameter : SearchParameter<OrderSearchParameterNames>
{
public OrderSearchParameter(OrderSearchParameterNames name, List<object> values)
{
Name = name;
Values = values;
}
}
Example of method using the inherited class:
public ApiResponse<OrderWellplate, ApiResponseStatus> SearchOrders(int currentPageIndex, int pageSize, List<OrderSearchParameter> searchParameters, OrderSortParameter sortParameter, out int recordCount)
If the type of the list is the same as the type of Name
public class SearchParameter<T>
{
public T Name { get; set; }
public List<T> Values { get; set; }
public SearchParameter(T name, List<T> values)
{
Name = name;
Values = values;
}
}
If the type of the list is different from the type of Name
public class SearchParameter<TName, TValues>
{
public TName Name { get; set; }
public List<TValues> { get; set; }
public SearchParameter(TName name, List<TValues> values)
{
Name = name;
Values = values;
}
}
Im learning c# online, and I just finished an exercise, were I should create a class called "People" and create 5 variables that can make the peoples uniqe:
public string name;
public int age;
public double heigth;
public double weigth;
public string nationality;
public int shoeSize;
I also created a class called "Bank" and declaired 4 members:
int accountNumber;
string firstName;
string lastName;
string bankName;
then, I got the question: "If you think that the bank class is associated with one person (People class) how would you use the class "People" in the class for "Bank" ?
Now I clearly didnĀ“t understand what was being ment.. Any ideas`?
Edit: when do I need the constructor method?
That's not a constructor, that's trying to teach you that you can have classes you created as properties inside another class you create.
In their example, one person is per bank, so you could have the People class as a property called Person to signify who the account belongs to. You can do this by adding the following to your Bank class:
public People person { get; set; }
In terms of a constructor, you'd need one if you wanted to set some default properties. Consider this constructor for Bank:
public Bank()
{
accountNumber = 1;
firstName = "Default";
lastName = "Default";
bankName = "Default";
person = new People();
}
See that last line that creates person? If you removed that, but then tried to do this.person.name you'd get a NullReferenceException. That's because by default your person would have the value of null.
It could be as simple as:
public class People // I would call it person though, as People is plural
{
public int age;
public double heigth;
public double weigth;
public string nationality;
public int shoeSize;
}
public class Bank // I would call it BankAccount though
{
int accountNumber;
string firstName;
string lastName;
string bankName;
// The answer to the question:
People owner; // <-- Here the bank account has a reference to the People class,
// you provided in the constructor
// And if you need the constructor
public Bank(People owner, int accountNumber)// <-- This is the constructor
{
this.accountNumber = accountNumber;
this.owner = owner;
} // <-- The constructor ends here.
}
How about
public class Person
{
//A property for Name
//A property for Address
}
In another class a property for collection of Persons
public List<Person> People { get; set; }
Thats the way I would go:
public class Person
{
public int Age { get; set; } // I would use properties and public properties are
// starting with a great letter
public double Heigth { get; set; }
public double Weigth { get; set; }
public string Nationality { get; set; }
public int ShoeSize { get; set; }
}
public class BankAccount
{
private Person _person; // private field for the person object
public int AccountNumber { get; private set; } // public propertie for the account
// number with a private setter
// because normally you want to read
// that from the outside but not set
// from the outside
public string FirstName
{
get { return _person.FirstName; }
}
public string LastName;
{
get { return _person.LastName; }
}
public string BankName { get; set; }
public Bank(Person person, int accountNumber)
{
AccountNumber = accountNumber;
_person = person;
}
}
Please allways write down the access parameters from properties, methods etc.