I'm very new to programming and I couldnt find an exact answer for my question by googling it so hopefully i'll make it as simple as possible to understand.
My public class MotherClass() has public int Id which should show current number stored in public static int idCounter. I want to inherit/share same idCounter in my public class ChildClass : MotherClass.
So when i make for ex. 2 new MotherClass() objects and lets say 2 new ChildClass() objects, their Id's should be: 1,2,3,4 (shared) and not like 1,2 and 1,2 (different counter for each class).
This is what i have:
public class MotherClass(){
public static int idCounter {get; set;}
public int Id { get; set; }
public string Name { get; set; }
static MotherClass(){
idCounter = 1;
}
public MotherClass(string name, int id = -1){
if(id == -1)
Id = idCounter++;
Name = name;
}
public class ChildClass : MotherClass{
public double Price { get; set; }
public ChildClass(string name, double price int id =-1) : base(name,id){
Price = price;
}
}
Here's one way you could do it:
public class MotherClass
{
public static int IdCounter { get; private set; } = 1;
public int Id { get; } = IdCounter++;
}
public class ChildClass : MotherClass { }
Each time you create a new MotherClass or ChildClass, IdCounter will be incremented.
Example:
Console.WriteLine(new MotherClass().Id); // 1
Console.WriteLine(new MotherClass().Id); // 2
Console.WriteLine(new ChildClass().Id); // 3
You should make the setter of IdCounter private then other classes cannot modify the value.
Related
My question is simple.
I am working with a testcase given to me in C#.
In this test case they have a Parent class containing all the methods and subclasses that will call those methods.
So as far as I know. You can do that by:
Class object = new Class(arguments);
Then call the parent methods like this object.Method()
Now the test I am working with has it written like this: Class.Method()
So just to make my question more clear here is an example of what they have:
Book harryPotterBook = new Book { title = "Harry Potter" };
var savedBook = Book.Find(harryPotterBook.Id);
and here is what I understand it should be:
var savedBook = harryPotterBook.Find(harryPotterBook.Id);
So is this possible? I just want to know what I am missing here.
Thank you.
I'm not sure I understand what you're trying to do right now, because in your example, you seem to be asking how to generate a class with a constructor. If you want to create a class constructor you have to write it like this:
public class Class
{
string name;
public Class(string pName)
{
name = pName;
}
}
Otherwise, if you know that this class is going to be used often as a standard. You can use interfaces:
interface IBasicClass
{
string name { get; set; }
string description { get; set; }
int numberOfPage { get; set; }
int currentPage { get; set; }
void NextPage();
void PreviousPage();
}
public class BasicClass : IBasicClass
{
public string name { get; set; }
public string description { get; set; }
public int numberOfPage { get; set; }
public int currentPage { get; set; }
//Default Constructor
public BasicClass()
{
name = "";
description = "";
numberOfPage = 0;
currentPage = 0;
}
//Constructor
public BasicClass(string pName, string pDescription, int pNumberOfPage)
{
name = pName;
description = pDescription;
numberOfPage = pNumberOfPage;
}
public void PreviousPage()
{
--currentPage;
}
public void NextPage()
{
++currentPage;
}
}
public class Class : MonoBehaviour
{
BasicClass _basicClass;
BasicClass _basicClass2;
void Start()
{
_basicClass = new BasicClass();
_basicClass2 = new BasicClass("Books", "It's a good book", 1);
}
void Update()
{
_basicClass.NextPage();
_basicClass2.NextPage();
}
}
I have many entities that use a UserId property of the same type.
Can I define a type (string or int, ...) that I can easily change as a variant for all?
Example:
public class Entity_One
{
public DefineMyType UserId { get; set; }
public string Property_Entity_One { get; set; }
}
public class Entity_Two
{
public DefineMyType UserId { get; set; }
public string Property_Entity_Two { get; set; }
}
const DefineMyType = string;
// or const DefineMyType = int;
// or const DefineMyType = Guid;
Constants can't be used like that.
Preprocessor may be used.
But we can use a generic:
public abstract class AbstractID<T>
{
static protected T Last = default;
public T Value { get; protected set; } // or perhaps init only with C# 9
}
Thus we can define some specialized IDs like:
public class NumberID<T> : AbstractID<T> where T : struct, IComparable, IFormattable
{
public NumberID()
{
Value = (T)( (dynamic)Last + 1 );
Last = Value;
}
}
public class GuidID : AbstractID<Guid>
{
public GuidID()
{
Value = Guid.NewGuid();
Last = Value;
}
}
public class StringID : AbstractID<string>
{
private string Generate()
{
return ...
}
public StringID()
{
Value = Generate();
Last = Value;
}
}
Then we can set the "default" ID type:
public class ManagedID : NumberID<int>
{
}
Or:
public class ManagedID : GuidID
{
}
Therefore we can easily change ManagedID for all code using it.
It only requires to change the ancestor class in the declaration.
And now that works:
public class EntityOne
{
public ManagedID UserId { get; } = new ManagedID();
public string PropertyEntityOne { get; set; }
}
public class EntityTwo
{
public ManagedID UserId { get; } = new ManagedID();
public ManagedID EntityOneId { get; }
public string PropertyEntityTwo { get; set; }
public EntityTwo(EntityOne one)
{
EntityOneId = one.UserId;
}
}
Test
var entity1 = new EntityOne();
var entity2 = new EntityOne();
var entity3 = new EntityTwo(entity1);
Console.WriteLine(entity1.UserId.Value);
Console.WriteLine(entity2.UserId.Value);
Console.WriteLine(entity3.UserId.Value + $" ({entity3.EntityOneId.Value})");
Result with an integer
1
2
3 (1)
Result with a GUID
3a189122-60fd-4dc5-9d7f-3cc4c83375f9
37a9c7de-8ed5-4d02-a1b9-f414db051335
2de962d6-cc91-4e78-b3dc-28acb0ba7f3b (3a189122-60fd-4dc5-9d7f-3cc4c83375f9)
Warning
Here, the use of numbers is very basic and not really reliable, especially beyond a local machine and after stopping the execution of the current process. Thus persistence somewhere of the last value is required for a real database, like in a config file or whatever.
GUID vs INT IDENTITY
Guid vs INT - Which is better as a primary key?
Int for identity/primary key and Guid for public identifier, best practices?
A small example to illustrate my question: I write a program that accesses a database. Most of the properties and methods are the same for every table. Therefore I try to use an abstract class. To delete, insert or update a row, no problem. But to retrieve rows, the Dml statement is different from table to table (here ??? should be replaced by the name of the table, but it is not always so trivial).
What solution?
Thank you,
Gilbert
public abstract class SQLiteAbstractTable
{
#region Properties (DB columns)
[PrimaryKey, AutoIncrement] public int Id { get; set; }
public DateTime DatCreation { get; set; }
public DateTime DatMaj { get; set; }
#endregion
#region Public methods
public static int Delete<T>(int pId)
{
int n = CgtDataSQLite.Cn.Delete<T>(pId);
return n;
}
// Called by : var LstEnr = SQLiteAbstractTable.GetLstInstance<SQLiteReference>();
public static List<T> GetLstInstance<T>() where T : SQLiteAbstractTable, new()
{
var LstEnr = CgtDataSQLite.Cn.Query<T>("SELECT * FROM ???");
return LstEnr;
}
public int Insert()
{
int n = CgtDataSQLite.Cn.Insert(this);
return n;
}
public int Update()
{
int n = CgtDataSQLite.Cn.Update(this);
return n;
}
#endregion
}
[Table("Reference")]
public class SQLiteReference : SQLiteAbstractTable
{
#region Properties (additional DB columns)
[MaxLength(8)] public string DatPublication { get; set; }
[NotNull, MaxLength(80)] public string Nom { get; set; }
#endregion
#region Constructors
public SQLiteReference()
{
}
public SQLiteReference(int id, int typeReferenceId, string datPublication, string nom, string nomAbrege, string url = null)
{
Id = id;
DatPublication = datPublication;
Nom = nom;
}
#endregion
}
I've got a function with List<> set as the parameter, which looks something like this:
private Double CalculateConsumption(List<GasConsumRecord> gasRecord)
{
...
foreach (var record in gasRecords){
var x = record.Counter;
var y = record.Pressure;
...
}
...
}
GasConsumRecord class has more properties but in this function I use only 2.
And I've got another class - AirConsumRecord which has the same 2 properties but other properties are different. Both classes have only properties, but no methods.
My question is: How can I use the same method for two different class List<> as parameter?
Thanks in advance.
You'll need your classes to implement the same interface, or derive from the same base class, which contains these two properties, then use a generic method with a type constraint:
If you use interfaces:
public interface IRecord {
int Counter { get; set; }
int Pressure { get; set; }
}
public class GasConsumRecord : IRecord {
public int Counter { get; set; }
public int Pressure { get; set; }
}
public class AirConsumRecord : IRecord {
public int Counter { get; set; }
public int Pressure { get; set; }
}
private Double CalculateConsumption<T>(List<T> records)
where T : IRecord
{
foreach (IRecord record in records){
var x = record.Counter;
var y = record.Pressure;
}
}
I have a base class with three field, but instead of initializing its field the normal way like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
public ParentClass(string Name, string Family, string Address)
{
this.Name = Name;
this.Family = Family;
this.Address = Address;
}
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(string Name, string Family, string Address, int StudentID, int StudentScore)
: base(Name, Family, Address)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass("John", "Greene", "45 Street", 76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I’ve initialized the fields in the ChildClass constructor without explicitly calling the base class constructor like this:
class ParentClass
{
public string Name { get; set; }
public string Family { get; set; }
public string Address { get; set; }
}
class ChildClass : ParentClass
{
public int StudentID { get; set; }
public int StudentScore { get; set; }
public ChildClass(int StudentID, int StudentScore)
{
Name = "John";
Family = "Greene";
Address = "45 Street";
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
static void Main(string[] args)
{
var Pro = new ChildClass(76, 25);
Console.WriteLine(Pro.Name + Pro.Family + Pro.Address + Pro.StudentID + Pro.StudentScore);
}
}
I know I could have initialized the parent class’s field in the parent class itself and this is a bogus example, but I was wondering if it is considered a good practice to do something like that in real life and more complex situations, is there any reason why I shouldn’t do something like this? as to not explicitly call the base class constructor?
Edit: I'm more concerned about not explicitly call the base class constructor and initializing it in subclass part, so I've edited the last part that mentioned the fields being exposed out.
As you've already seen, the fields are already "exposed". Your could still get to those variables from the derived class in the first example.
As to not using a base class constructor being good practice, I would say not. By only having a parameterized base class constructor, you are making sure that future implementers of that class initialize the base class properties. For example, in your second I could write:
public ChildClass(int StudentID, int StudentScore)
{
this.StudentID = StudentID;
this.StudentScore = StudentScore;
}
With no errors. Other than that there are very few differences between your samples.