C# looking for a pointer workaround - c#

I'm trying to create a foreign key in a class, B, to the id of another class, A. The problem is that I can't verify the ID of A's objects until near the end of the program when all my instances of B have already been created. I would like to be able to instantiate objects of B with a reference to the id of an A object so that when the id of the A object changes, so does the value of the foreign key in B. I know I can't do that directly in C# without using 'unsafe' mode so I've been looking for alternative methods. As a last resort I could do a loop at the end through all my B objects, but B is actually many different classes and objects and there are enough of them that I would much prefer a more efficient solution.
Here's a rough example of the logic that I need.
using System;
namespace sandbox
{
public class A
{
public int ID;
public A(int id)
{
ID = id;
}
}
public class B
{
public int reftoAID;
public B(int id)
{
reftoAID = id;
}
}
public class TestMain
{
static void Main()
{
A a = new A(1);
B b = new B(a.ID);
a.ID = 3;
Console.WriteLine(b.reftoAID); //prints 1, but I need 3
Console.ReadLine();
}
}
}
I have tried creating a wrapper class with an int property that holds the id, but I haven't been able to figure out how to get it into the database using linqtodb. I thought I would be able to just define an (int) cast, but that doesn't work. From what I can tell, linqtodb uses the System.Data.DbType enum to determine the type and I don't know if there's a way to have it convert before the lookup.
I'm looking either for a new approach to the problem or a way of converting the wrapper class in such a way that it can be written to the database.

C# doesn't use pointers for referencing objects. Instead, C# has the concept of value types and reference types. All classes are reference types, which means that a variable of that type is a reference to an object. This is very similar to pointers in other programming languages.
Using direct references, your code would look like this (some name changes for clarity):
public class ClassA
{
public int ID;
public ClassA(int id)
{
ID = id;
}
}
public class ClassB
{
public ClassA A;
public ClassB(ClassA a)
{
A = a;
}
}
public class TestMain
{
static void Main(string[] args)
{
ClassA a = new ClassA(1);
ClassB b = new ClassB(a);
a.ID = 3;
Console.WriteLine(b.A.ID); //prints 3
Console.ReadLine();
}
}
The constructor for ClassB takes a reference to an object of type ClassA, so any changes to that object are reflected when it is accessed through the A property of ClassB.

I was able to solve this using properties, which I had completely forgotten about when I asked this question initially. Using BJ Myers' example:
public class ClassB
{
ClassA A;
public int AID { get {return A.ID;} }
public ClassB(ClassA a)
{
A = a;
}
}

Related

EF6 - BaseClass data duplication

I have a base class A and derived class B. B is introduced in my latest migration. I am going for a Table-per-Type inheritance. There can be many Bs for one A. The error I am getting when trying to update-database is related the Index on A.Designation, because the DB gets populated by the Seed method. I do understand where this error comes from, but I do not know how to avoid it.
The base class:
[Table("As")]
class A
{
[Key]
public Id { get; set; }
[Index(IsUnique = true)]
public string Designation { get; set; }
// This is mapped via EF and required by Bs constructor
public ICollection<SomeType> SomeType { get; set; }
// Parameter less constructor for EntityFramework
private A() { }
public A(string designation)
{
Designation = designation;
}
}
The derived class:
[Table("Bs")]
class B : A
{
public B(A a) : base(a.designation)
{
foreach (SomeType someType in A.SomeTypes)
{
// Do something
}
}
}
So in the Seed method first an instance a of A, then an instance b of B based on a is added to the DB.
As I understand it, calling new B(a) creates a new instance of A which also is added to the DB which fails because of the unique index.
How do I avoid this?
I want the data to be referenced, not duplicated. I guess it would be possible to use a Table-per-Hierarchy scheme but that would duplicate the data of A for each B, (right?) which I would like to avoid, especially because A.SomeEntities would have its entries duplicated as well.
Another possibility that just popped into my mind, is passing the the Id of a to b's constructor, but that would then have to call the DbContext and probably imply some other weirdness I am missing right now.
Looks like you are trying to link with existing object instead of class inheritance?
Why not create a link between your b and a?
[Table("Bs")]
class B
{
public A referredA {get;set;}
public B(A a)
{
referredA=a;
}
}

C# how can I preserve data between class instances?

Apologies for the vague title, but I am not really sure how else to explain it.
Given Class A, B and C.
If Class A contains a List, how can I preserve the data in that list so that Class B and C can access the data in the list (even if B and C both new up their own instance of Class A)?
Classes B and C must create their own instances (this is out of my control).
I am using this class as my object data source, and let's say I cannot modify the contents of Class C.
Following is an example class:
[DataObject]
public class Product
{
public string Name {get; set;}
public string Category {get; set;}
public int ID {get; set;}
public List<Product> ProductList =
new List<Product>();
[DataObjectMethod(DataObjectMethodType.Select)]
public IEnumerable<Product> GenerateReport()
{
return ProductList;
}
}
Use static as defined here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/static
Then you will be able to access the class properties instead of instance properties.
You have multiple options to implement this. As said in other answer you can use Static property/field in Class A for accessing list.
Second option is to use Dependency injection. Create constructors of class B and class C so that they must be initialized by passing in instance of A.
e.g.
class A
{
public List<object> AList {get;set;}
}
class B
{
private A localInstance;
public B(A instance)
{
localInstance = instance;
}
public void SomeMethod()
{
// access to list from instance of A
var a = localInstance.AList
}
}
// Similar implementation for class c

Using the constructor of the base class when creating new object of derived class?

Public class A
{
...
}
Public class B:A
{
...
}
Public class Prog
{
public static void Main()
{
A myA = new B();
}
}
If myA is an instance of A class, why I use B constructor, and how it differ from this:
A myA = new A();
also this code may be closer to this issue:
I know this may be very basic question, but I'm really confused.
You don't have to use the B constructor, only if you want an instance of B that inherits A.
You can also setup B so that is calls the constructor of A for you, eg:
public class A
{
public A()
{
}
}
public class B : A
{
public B() : base()
{
}
}
It all entirely depends on the implementation of your A and B classes and what you want to use them for.
Edit:
In light of your image, the reason you are calling like Vehicle c = new Car() is because the object you are actually creating is a Car but you still want or need to use aspects of the base class. Having this base class means you can have common properties between implementing classes.
For example:
public class Vehicle
{
public Vehicle()
{
}
public int NumberOfWheels { get; set; }
}
public class Car : Vehicle
{
public Car() : base()
{
NumberOfWheels = 4;
}
}
public class Motorbike : Vehicle
{
public Motorbike() : base()
{
NumberOfWheels = 2;
}
}
This case allows you to only define NumberOfWheels once and just set the value appropriately for the implementation you are writing. You can do the same thing with methods using virtual methods.
A myA = new B();
This is creating an object of type B. It is not creating an object of type A. However, you are casting the object to A. Casting in layterms essentially means you are saying 'View this object as if it were an A. Ignore the fact that it may be a B. Only show me methods and properties which were defined in the class A).
Note that you can re-cast it back to B, which does not change the object whatsoever:
B myB = (B)myA;
The difference between this:
A myA = new A();
and this:
A myA = new B();
Is that the first statement is creating a physical object of type A. Any overrides or new method/properties/fields defined in B will not be created. The second statement will create a physical object of type B, but to view it (even temporarily) as an A

Can I create a property in a struct with a "set" only accessible by a single concrete class?

I know it sounds a bit weird, but I will try to explain it: suppose I have a class with a lot of properties, and all of them are read-only, so this class is the only one which can modify its properties (it is listening to an event, and fills the properties with the information contained on that event).
But, I want to encapsulate some of the properties on some structs, to create a well organized hierarchy, so these structs'properties should be read-only too, except for the owner class. For example:
public class A
{
private int a1;
public int A1
{
get{ return a1; }
}
private B structB;
public B StructB
{
get{ return structB; }
}
private method eventListenerMethod(...)
{
a1 = someValue;
structB.B1 = otherValue; //I want that only this class can modify this property!
}
}
public struct B
{
private int b1;
public int B1
{
get{ return b1; } // This property should be modifiable for Class A!!
}
}
I think I cannot do that, but does anyone know how can I achieve it?
Thank you very much in advance.
Seems what you're after is the "friend" keyword in C++. However, it doesn't exist in C#, but "internal" is a good compromise. So, just make a "internal set" property, which'll be accessible (only) within the assembly. So other people who'll use your assembly won't have access to it
Change the struct to a class and make it private, but put the definition of it inside class A.
This will mean only class A has access to its properties. All the properties inside class B can then be public (because only the class in which it's defined has access to it).
This will cause a compiler error because class B will be private, but is exposed on a public property. To fix this, make a public interface to expose as the type IClassB (bad name but you get the idea) and change the property type to be the interface. Ensure this interface has only get accessors on the property method signatures.
Something like this should work:
public class A : IClassB
{
public IClassB B { get; }
private class B : IClassB
{
public int B1 { get; }
}
}
public interface IClassB
{
int B1 { get; }
}

Upcasting in .NET using generics

So I've got a class like this:
public class A {
internal A(int i) { ... }
public int Foo { get; set; }
}
This class is then inherited by a bunch of generated classes, eg:
public class B : A {
...
}
The int based constructor isn't exposed to the inherited class (for design reasons I don't want it exposed). In my library which holds the definition for class A I've got a method like this:
public T Load<T>() where T : A {
//do some stuff, create an instance of T from an int, then return it
}
And then I'd use it like this:
B b = Helper.Load<B>();
Since the constructor I want to use isn't exposed to class B when I do typeof(T).GetConstructor(typeof(int)) I don't get the constructor back, so I want thinking that I'd do this:
return (T)new A(/*some int */);
But that gives me a runtime error System.InvalidCastException, that I can't cast a type A to type B.
How do I go about achieving this upcasting?
You can just use default constructors so you can instantiate objects of type T with the new() constraint. Then class A can have a virtual (or abstract to your liking) method that takes an int as an argument and initializes the object after the constructor has run.
public class A {
internal A() { }
internal Initialize(int i) { Foo = i; }
public int Foo { get; set; }
}
public class B : A {
internal B() { }
}
...
public T Load<T>() where T : A, new() {
var ret = new T();
ret.Initialize(i);
return ret;
}
If you intend some sort of factory pattern, you don't need to hesitate initializing parts of an object outside the constructor call as long as it is done before you return the object to the caller's control.
From what I understood, T derives from A, so you can't cast A to T.
You can't upcast A to B in your example, because:
return (T)new A(/*some int */);
Instantiates an A, which is not a B. Just because a "B is an A" does not mean "A is a B". You would have to first instantiate a B, cast it to an A, do what you want, and then upcast it back to a B.
I'm not sure if this is will compile, but you could try this:
T blah = new T(5); //this means your B will need to implement a int constructor
A blah2 = (A)blah;
//operate on A specific operations in blah2
T upcasted = (T)blah2;
//alternatively
T upcasted = blah2 as T;
Consider refactoring your contructor such that you initialize the integer as a property, instead of a parameter of the constructor. I strive to have default(no parameters) contructors so that generic code can instantiate the class easily.
You cant do this, change your design.

Categories