generic method access hidden property in c# - c#

I'm currently having trouble and I have no clue how to fix it.
I have 2 classes:
class A
{
public string MyParam { get; set; }
}
class B : A
{
public new string MyParam { get { return base.MyParam != null ? base.MyParam.Substring(1) : null; } }
}
When I try to access the B.MyParam it works when I have a the correct type, but in most of my methods I have a generic type
with :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public class A
{
public string MyParam { get; set; }
}
public class B : A
{
public new string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
public static void MyMethod<T>(T variable) where T : A
{
Console.WriteLine(variable.MyParam);//this print hello
Console.WriteLine((variable as B).MyParam);//this print ello (exactly what i want)
Console.WriteLine(typeof(T)); // this print ConsoleApplication1.Program+A
Console.WriteLine(variable.GetType()); // this print ConsoleApplication1.Program+B
// so i need something like that
Console.WriteLine((variable as variable.GetType()).MyParam); // this line is invalid
}
static void Main(string[] args)
{
A a = new B();
a.MyParam = "Hello";
Console.WriteLine(a.GetType());
MyMethod(a);
Console.ReadKey();
}
}
}
Is there a way to do it?
Thank you in advance.
EDIT: it seems that what i want is :
dynamic variable2 = Convert.ChangeType(variable, variable.GetType());
Console.WriteLine(variable2.MyParam);

Your code doesn´t make any sense. If A inherits from B you´ll need A to override the base-implementation for your property. So I´ll assume you should rethink your inheritance-chain.
You can use override for this. Thus when your variable-parameter is of your base-class (I renamed that to A) you´re calling the base-method, if it´s a derived instance (here B) you´re calling the override:
class A
{
public virtual string MyParam { get; }
}
class B : A // note here that B derives from A, not the other way round
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; },
set { ... }
}
}
EDIT: While new intrduces a new member which (accidentally) has the same name (and signature) as the base-member it effectivly hides the base-member. Thus you effectivly have two members. Your only way to indicate which member should be used is by casting your instance to the desired class from which you need the implementation. However this somehow breaks the purpose of generics as the generic member has to know the exact types that are possible for the type-parameter.
Anyway this seems like broken design to me, as you´re actually creating a new member which has another meaning. So you should also give it a new name.

Based on your generic method, I think all you need is an interface.
public interface IMyParam
{
string MyParam { get; set; }
}
Your classes.
class A : IMyParam
{
public virtual string MyParam { get; set; }
}
class B : A
{
public override string MyParam
{
get { return base.MyParam != null ? base.MyParam.Substring(1) : null; }
}
}
And your method, won't need to be generic.
public void MyMethod(IMyParam variable)
{
// Your logic here, for example.
Console.WriteLine(variable.MyParam);
}
Calling your method.
A a = new A();
a.MyParam = "Hello";
B b = new B();
b.MyParam = "Hello";
A ab = new B();
ab.MyParam = "Hello";
MyMethod(a); // Prints Hello
MyMethod(b); // Prints ello
MyMethod(ab); // Prints ello

Related

ReferenceEquals with casting challenge. Casting to child type make ReferenceEquals return false

Casting does not make copies of objects. More concretely IEnumerable.Cast, according to this resource, which makes total sense. However for this app, find fiddle, reference equals is false if I change the log at the end from the Cast<BaseClass> to Cast<DerivedClass1>. Check logs at the main program.
are equal: True areEqualRef: True areEqualRef: False
Posting the code, just in case, omit it of you get my point playing around with the fiddle :)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp17
{
public class BaseClass {
string name = "I am base";
public Type type;
public enum Type {
a,b,c,d
}
public BaseClass(Type type) {
this.type = type;
}
}
public class DerivedClass1 : BaseClass
{
string name = "I am derivedA";
public DerivedClass1(): base(Type.a) {
}
}
public class DerivedClass2 : BaseClass
{
string name = "I am derivedB";
public DerivedClass2() : base(Type.b)
{
}
}
public class Foo
{
public Dictionary<BaseClass.Type, List<BaseClass>> dict = new Dictionary<BaseClass.Type, List<BaseClass>>();
public Foo() {
dict[BaseClass.Type.a] = new List<BaseClass>();
dict[BaseClass.Type.b] = new List<BaseClass>();
dict[BaseClass.Type.c] = new List<BaseClass>();
dict[BaseClass.Type.d] = new List<BaseClass>();
AddItem(new DerivedClass1());
AddItem(new DerivedClass1());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
AddItem(new DerivedClass2());
}
public IEnumerable<T> GetEnumByType<T>(BaseClass.Type type) where T : BaseClass
{
if (dict.ContainsKey(type))
{
if (type == BaseClass.Type.a)
{
Console.WriteLine($"are equal: { object.ReferenceEquals(dict[type].Cast<T>(), dict[BaseClass.Type.a])}");
}
return dict[type].Cast<T>();
}
return null;
}
public void AddItem<T>(T item) where T : BaseClass
{
dict[item.type].Add(item);
}
}
class Program
{
static void Main(string[] args)
{
Foo foo = new Foo();
IEnumerable myList = foo.GetEnumByType<BaseClass>(BaseClass.Type.a);
Console.WriteLine($"areEqualRef: {object.ReferenceEquals(foo.dict[BaseClass.Type.a].Cast<BaseClass>(), foo.dict[BaseClass.Type.a])}");
Console.ReadLine();
}
}
}
Update:
Updated the fiddle with both logs to avoid the need of copy/pasting
You need to notionally separate what is being compared here. When it says that Enumerable.Cast<T> doesn't make copies of objects, it is talking about the individual objects in the sequence. Not the sequence itself. In order to perform the necessary reshaping, the sequence returned from the Cast<T> method is a different wrapper/decorator instance over the original sequence.
Since you're using ReferenceEquals on the sequence, this will report false. However, if you were to compare each object from the sequences (pairwise in turn), you would find that those were the same objects.

C# generics type interference strange behaviour

Consider the following code :
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
Print(a);
Print(b);
Console.WriteLine(b.Hello);
Console.ReadLine();
}
static void Print<T>(T t) where T : A
{
Console.WriteLine(typeof(T));
Console.WriteLine(t.GetType());
Console.WriteLine(t.Hello);
}
}
public class A
{
public string Hello { get { return "HelloA"; } }
}
public class B : A
{
public new string Hello { get { return "HelloB"; } }
}
The output I got (.NET FW 4.5)
//Print(a)
A
A
HelloA
//Print(b)
B
B
HelloA
//Explicit Writeline
HelloB
Can anyone explain how I got the 2nd HelloA, as I was expecting HelloB ?
public new string Hello { get { return "HelloB"; } }
The new keyword creates a new function which just happens to have the same name as the old one. Thus, B now has two methods: Hello (A), which is executed when invoked through a variable of compile-time type A, and Hello (B), which is executed when invoked through a variable of compile-time type B (or a subtype thereof).
Since your generic parameter is T : A, the compiler compiles t.Hello as a call to Hello (A).
B shadows (or hides) method Hello rather than overriding it.
What you probably wanted to write was:
public class A
{
public virtual string Hello { get { return "HelloA"; } }
}
public class B : A
{
public override string Hello { get { return "HelloB"; } }
}
Note that the base method is declared as virtual, and the subclass method as override.

C# How to change the Variable Value in the BaseClass if the new Variable into the derived Class are changed

I have a bigger Projekt and I would like to change a variable value into the BaseClass if the variable value into the derived class are changed.
Here a simple Example.
What I want are, if I change the value Obj.ModelTyp.Name to “Name123“ then the Base.ModelTyp.Name gets the same value “Name123“ automatically.
Is there a simple way to do that?
Thanks Steffen
namespace Question
{
class Program
{
static void Main(string[] args)
{
DataObjekt Obj = new DataObjekt();
Obj.ModelTyp.Name = "Name123"; // is there a Way to Change Base.ModelTyp.Name
// if Obj.ModelTyp.Name is changed?
Obj.ModelTyp.Data = "4567";
Obj.DoSomithing();
}
}
public class FirstBaseClass
{
public FirstBaseClass() { ModelTyp = new BaseType(); }
public BaseType ModelTyp { get; set; }
}
public class SecondBaseClass : FirstBaseClass
{
public void DoSomithing()
{
string Test = this.ModelTyp.Name; // there is nothing because Base.ModelTyp.Name
//but I Want to have "Name123"
}
}
public class DataObjekt : SecondBaseClass
{
public DataObjekt() { ModelTyp = new ObjektData(); }
new public ObjektData ModelTyp { get; set; }
}
public class BaseType
{
public string Name { get; set; }
}
public class ObjektData : BaseType
{
public string Data { get; set; }
}
}
Your classes' relationships seem really complicated and convoluted. You should probably consider simplifying it a bit.
Anyway, the reason why your code does not work now is because you hid the base class' ModelTyp property, and created another new ModelTyp property in DataObjekt. Hopefully you already knew this.
But you don't really want to create a brand new, separate property, do you? You just want to change the type of ModelTyp to ObjektData. Therefore, you can just make DataObjekt.ModelTyp refer to the same thing as FirstBaseClass.ModelTyp in the constructor:
public DataObjekt() {
ModelTyp = new ObjektData();
base.ModelTyp = this.ModelTyp; // <- this line
}

How to know the calling Class Name?

Is there a way know which class has called a function in another class.
Eg:
public class A
{
public static string Aa = "test";
public void test()
{
B.testB();
}
}
public class B
{
public static void testB()
{
string Bb = A.Aa;
}
}
In the above example, i know the class A function has called the function in class B. But if there are many classes which will call the function in class B and all of those classes will have variable Aa in common, so how can i read its value and assign it to Bb. So in simple
string Bb = CalledClassName.Aa;
You could use the CallerMemberNameAttribute that was added with .NET 4.5. This will only get you the member name though:
public void SomeMethod ()
{
OtherMethod();
}
public void OtherMethod ([CallerMemberName] string memberName = null)
{
Console.WriteLine(memberName);
}
The attribute will fill the optional parameter at compile time, so it will actually call OtherMethod("SomeMethod").
You could also use a combination of accessing the stack trace and using reflection to read the Aa property of the type of the calling method. Note that this accesses debugging information, and is very vulnerable to changes in your code. It also has a bad performance, so you should avoid it. But just to show you how to use it:
public static void testB()
{
StackTrace stackTrace = new StackTrace();
Type callingType = stackTrace.GetFrame(1).GetMethod().DeclaringType;
FieldInfo field = callingType.GetField("Aa", BindingFlags.Public | BindingFlags.Static);
string Bb = (string) field.GetValue(null);
Console.WriteLine(Bb);
}
Use an interface, pass that in:
public interface AaInterface {
public string GetAa();
}
public class A : AaInterface
{
public static string Aa = "test";
public GetAa() { return Aa; }
public void test()
{
B.testB(this);
}
}
public class B
{
public static void testB(AaInterface pAa)
{
string Bb = pAa.GetAa();
}
}
I guess you are looking for something different than you are asking.
You should pass the instance of A to your method. All calling methods should pass the instance based on an interface. In that interface you put the properties and methods you want to share. In that way you can call the 'same' method for every passed instance.
public interface ISomeInterface
{
string Aa {get;}
}
public class A : ISomeInterface
{
public string Aa {get { return "a"; } }
}
Then you can pass it to this method:
public static void testB(ISomeInterface something)
{
string Bb = something.Aa;
}
Note that in this case, Aa is not allowed to be static. You could wrap that static in an instance property though.
If i understood your question correctly then you can pass a reference to a class instance in method as parameter then use 'is' operator to check its type:
public class A
{
public static string Aa = "test";
public void test(object calledClass)
{
if(calledClass is B) Aa = calledClass.Bb;
}
}
When you call this static method from class B just put :
A.Test(this)
P.S.
This is just an example of logic that you can use to achieve what you want
I geuss you can do something like this:
public class A {
public void test() {
B.testB(this);
}
}
public class B {
public static void testB(object sender) {
String className = sender.GetType().Name;
}
}
//To call
A a = new A();
a.test();

Unable to perform cast

I need to have a wrapper class that exposes some properties of my entity class called ProfileEntity.
I tried doing it by deriving from this entity and then creating properties that return specific entity properties, but it says I cannot cast from ProfileEntity to ProfileEntityWrapper.
When I try to put the return values of a method that returns a 'ProfileEntity' into the wrapper I get the above error.
How do I create such a wrapper class that is castable?
Example
class ProfileEntityWrapper : ProfileEntity
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class Someclass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity; // example of method returning this object
}
}
public class SomeOtherlClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
ProfileEntityWrapper ew = (ProfileEntityWrapper)sc.SomeMethod(); // Cannot do this cast!!!
}
}
You cannot cast an object of ProfileEntity to ProfileEntityWrapper.
var entity = new ProfileEntity(); // this object is only of type ProfileEntity
var wrapper = new ProfileEntityWrapper(); // this object can be used as both ProfileEntityWrapper and ProfileEntity
You probably want to return a ProfileEntityWrapper in SomeMethod():
public class Someclass
{
public ProfileEntity SomeMethod()
{
return new ProfileEntityWrapper(); // it's legal to return a ProfileEntity
}
}
No, that is not possible.
To accomplish this problem you can maybe try this one:
public class ProfileEntity
{
public string ProfileEntityName { get; set; }
}
public class ProfileEntityWrapper
{
public ProfileEntityWrapper(ProfileEntity entity)
{
Entity = entity;
}
public ProfileEntity Entity { get; private set; }
public string Name
{
get
{
return Entity.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
// example of method returning this object
ProfileEntity temp = new ProfileEntity();
return temp;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
//Create a new Wrapper for an existing Entity
ProfileEntityWrapper ew = new ProfileEntityWrapper(sc.SomeMethod());
}
}
If you are allowed to edit the ProfileEntity class, or if the ProfileEntity class is a generated partial class, you could add an interface instead of using a wrapper. You wouldn't need to do any casting with an interface either. Example:
public interface IProfile
{
string Name { get; }
}
public partial class ProfileEntity : IProfile
{
public string Name
{
get
{
return this.ProfileEntityName;
}
}
}
public class SomeClass
{
public ProfileEntity SomeMethod()
{
return ProfileEntity;
}
}
public class SomeOtherClass
{
SomeClass sc = new SomeClass();
public void DoSomething()
{
IProfile ew = sc.SomeMethod();
}
}
The IProfile instance will only provide access to the Name property.
This's no correct code from polymorphism aspect.
If we will take the famous polymorphism example when there're base Shape class and Circle, Polygon and Rectangle classes that extend the Shape class, your code will try to cast some shape into circle and as you understand this's invalid casting operation.
So to make this code work you must be sure that SomeClass.SomeMethod() will return instance of ProfileEntityWrapper or perform type check before the casting, like this:
ProfileEntity temp = sc.SomeMethod();
if(temp is ProfileEntityWrapper)
ProfileEntityWrapper ew = (ProfileEntityWrapper) temp;

Categories

Resources