Overriden Properties and TargetInvocationException - c#

I'm trying to call an overriden property from a base constructor but I'm receiving a System.Reflection.TargetInvovationException("Object reference not set to an instance of an object."). Why is this error being thrown and can anything be done to avoid it?
I would have expected the constructor to have just called the overriden property.
Here is a stripped down example:
// Call that generates exception
var foo = new Foo();
public class Foo : Bah {
public Foo() : base("Foo!") {}
public override string Name {
get { return _name + "123"; }
set { _name = value; }
}
}
public class Bah {
protected string _name;
public Bah(string name) {
Name = name; // << -- Exception here
}
public virtual string Name {
get { return _name; }
set { _name = value; }
}
}

You have some other issue going on. The code, as typed, works. Try this fully functional program to see, which prints (as expected) "Foo!123":
using System;
namespace Test
{
public class Program
{
private static void Main()
{
var foo = new Foo();
Console.WriteLine(foo.Name);
Console.ReadKey();
}
}
public class Foo : Bah
{
public Foo() : base("Foo!") { }
public override string Name
{
get { return _name + "123"; }
set { _name = value; }
}
}
public class Bah
{
protected string _name;
public Bah(string name)
{
Name = name; // << -- No Exception here (or anywhere!)
}
public virtual string Name
{
get { return _name; }
set { _name = value; }
}
}
}
That being said, calling virtual methods (including Property accessor methods) in a constructor is a very bad idea. It can lead to very odd behavior, which is likely the culprit in your real code.

Related

How does applying a Rename Method to change a name with get/set in c# work?

I have been doing an assignment recently but remain stuck/confused as to how the get/set property works. I have read a lot but can't seem to find what I am looking for.
The following code is from the assignment:
Animal cat = new Animal("Epicat");
cat.WhoAmI(); //Displays "I am an animal !"
cat.Describe(); //Displays "My name is Epicat."
cat.Name = "Moumoune"; //Doesn't work
cat.Rename("Moumoune"); //Changes the name
cat.Name; //return "Moumoune"
This is what I have coded so far:
(Ignore the throw new exceptions.)
public class Animal
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
#region Constructor
public Animal(string name)
{
this.name = name;
//throw new TargetInvocationException(new InvalidOperationException("Constructor is not implemented yet"));
}
#endregion Constructor
#region Methods
public virtual void WhoAmI()
{
Console.WriteLine("I am an animal !");
//throw new NotImplementedException("Please fix this quickly");
}
public virtual void Describe()
{
Console.WriteLine("My name is {0}.", name);
//throw new NotImplementedException("Please fix this quickly");
}
public void Rename(string NewName)
{
name = NewName;
//throw new NotImplementedException("Please fix this quickly");
}
#endregion Methods
}
I don't comprehend how the cat.Name = "Moumoune" doesn't edit (according to the assignment) the get/set name and why it wouldn't work.
And why would cat.Rename and cat.Name change anything?
I think, what meant is - you can't assign through Name property. This is achieavable through simple omittion of unneeded setter:
public class Animal
{
private string name;
public string Name
{
get { return name; }
//set { name = value; } just comment it out
}
public Animal(string name)
{
this.name = name;
}
public virtual void WhoAmI()
{
Console.WriteLine("I am an animal !");
}
public virtual void Describe()
{
Console.WriteLine("My name is {0}.", name);
}
public void Rename(string NewName)
{
name = NewName;
}
}
So, this will not even compile:
var a = new Animal("foo");
a.Name = "bar";
If you want for it to compile, but don't do a thing....just don't do a thing:
public class Animal
{
private string name;
public string Name
{
get { return name; }
set { /*name = value;*/ } //just don't do a thing.
}
public Animal(string name)
{
The following example correctly implements Rename. You can rename through Name, or Rename. Remove the setter from Name if you don't want to allow assignment.
e.g.
public string Name { get { return name; } }
Remember that name and Name are different (case sensitive). Name is a property, name is a field.
void Main()
{
var test = new Animal();
test.Name.Dump();
test.Name = "new name 1";
test.Name.Dump();
test.Rename("new name 2");
test.Name.Dump();
}
// Define other methods and classes here
class Animal
{
public string Name { get { return name; } set { name = value; } }
// Remove the setter here if you don't want to allow assignment through Name
// e.g. public string Name { get { return name; } }
private string name;
public void Rename(string NewName)
{
name = NewName;
}
}
Output
null
new name 1
new name 2
Remove the setter from Name if you don't want to allow assignment. e.g.
public string Name { get { return name; } }

How do i use this class in the main function? Dictionaries and indexers (Collections)

I am trying to add entries in dictionary array list but i don't know which arguments to set in the People Class in the main function.
public class People : DictionaryBase
{
public void Add(Person newPerson)
{
Dictionary.Add(newPerson.Name, newPerson);
}
public void Remove(string name)
{
Dictionary.Remove(name);
}
public Person this[string name]
{
get
{
return (Person)Dictionary[name];
}
set
{
Dictionary[name] = value;
}
}
}
public class Person
{
private string name;
private int age;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
}
using this seem to give me error
static void Main(string[] args)
{
People peop = new People();
peop.Add("Josh", new Person("Josh"));
}
Error 2 No overload for method 'Add' takes 2 arguments
This peop.Add("Josh", new Person("Josh"));
should be this
var josh = new Person() // parameterless constructor.
{
Name = "Josh" //Setter for name.
};
peop.Add(josh);//adds person to dictionary.
The class People has the method Add which only takes one argument: a Person object. The Add on the people class method will take care of adding the it to the dictionary for you and supplying both the name (string) argument and the Person argument.
Your Person class only has a parameterless constructor, which means that you need to set your Name in the setter. You can do this when you instantiate the object like above.
For your design this would solve the problem:
public class People : DictionaryBase
{
public void Add(string key, Person newPerson)
{
Dictionary.Add(key , newPerson);
}
public void Remove(string name)
{
Dictionary.Remove(name);
}
public Person this[string name]
{
get
{
return (Person)Dictionary[name];
}
set
{
Dictionary[name] = value;
}
}
}
public class Person
{
private string name;
private int age;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
}
And in Main:
People peop = new People();
peop.Add("Josh", new Person() { Name = "Josh" });

Deserializing "old" xml into new class instance

I've had a class which looked like
public class MyClass
{
public string EmployerName;
public string EmployerSurname;
public string EmploeeName;
public string EmploeeSurname;
}
I've refactored the code above to this:
public class MyClass
{
public MyClass()
{
Employer = new PersonInfo();
Emploee = new PersonInfo();
}
public class PersonInfo
{
public string Name;
public string Surname;
}
public PersonInfo Emploee;
public PersonInfo Employer;
[Obsolete]
public string EmploeeName
{
get
{
return Emploee.Name;
}
set
{
Emploee.Name = value;
}
}
[Obsolete]
public string EmploeeSurname
{
get
{
return Emploee.Surname;
}
set
{
Emploee.Surname= value;
}
}
[Obsolete]
public string EmployerName
{
get
{
return Employer.Name;
}
set
{
Employer.Name = value;
}
}
[Obsolete]
public string EmployerSurname
{
get
{
return Employer.Surname;
}
set
{
Employer.Surname = value;
}
}
Problem is, that when deserializing XMLs, which were serialized from old class version, I hoped that the new properties would work, and fields of the inner objects would be filled, but they don't.
Any ideas how, besides implementing IXmlSerializable, I could modify the new class to support both new and old versions of XMLs? Or maybe IXmlSerializable is the only way?
Do you only want to support the old ones for deserialization? if so, you could have:
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public string EmploeeName {
get { return Emploee.Name; }
set { Emploee.Name = value; }
}
public bool ShouldSerializeEmploeeName() { return false;}
The bool method tells XmlSerializer never to write this, but it will still be read. [Browsable] tells it not to appear in things like DataGridView, and [EditorBrowsable] tells it not to appear in intellisense (only applies to code referencing the dll, not the project, nor code in the same project).

Override only Get accessor

I got an abstract class :
abstract class ClassBase
{
public abstract string Test { get; }
}
I want to derive it and by the way add a set accesor
class ClassDerive : ClassBase
{
string _s;
public override string Test
{
get { return _s; }
set { _s = value; }
}
}
I can't do that because i may not override set
class ClassDerive2 : ClassBase
{
string _s;
public string Test
{
override get { return _s; }
set { _s = value; }
}
}
Syntax error
class ClassDerive3 : ClassBase
{
string _s;
public override string ClassBase.Test
{
get { return _s; }
}
public string Test
{
set { _s = value; }
}
}
Syntax error
Any Idea ???
thx
You cannot do exactly what you want to do but here is a workaround:
abstract class ClassBase
{
public abstract String Test { get; }
}
class ClassDerive : ClassBase
{
string _s;
public override string Test
{
get { return _s; }
}
public void SetTest(String test)
{
this._s = test;
}
}
This will make Test only settable in ClassDerived via the public SetTest method. I know this is not as clean as using the property's setter but it is about as good as it's going to get.
If at first you have defined a read-only property in a type, you can't later change it to a read/write property in a derived class. That's simply how .NET works, and can't be changed.
If, on the other hand, you define an interface with a read-only property, you can later implement that interface in a class with a writable property.
If you'd like to share what you are trying to achieve, perhaps we can come up with a design that works and can compile :)
Another way:
abstract class ClassBase
{
public abstract string Test { get; }
}
class ClassDerive : ClassBase
{
string _s;
protected void setTest(string s)
{
_s = s;
}
public override string Test
{
get { return _s; }
}
}
class ClassDerive2 : ClassDerive
{
public new string Test
{
get { return base.Test; }
set { setTest(value); }
}
}
class Program
{
static void Main(string[] args)
{
var cd2 = new ClassDerive2();
cd2.Test = "asdf";
Console.WriteLine(cd2.Test);
}
}
My first thought was also to implement it as an interface. If this fits in with your design, the following code will work:
public interface TestInterface
{
string TestProperty { get; }
}
public class TestClass : TestInterface
{
public string TestProperty
{
get { return "test"; }
set { string t = value; }
}
}
No you cant, sorry. It is by design, so it's the law.

LinFu - can't quite see how to do what I want

Just found LinFu - looks very impressive, but I can't quite see how to do what I want to do - which is multiple inheritance by mixin (composition/delegation as I'd say in my VB5/6 days - when I had a tool to generate the tedious repetitive delegation code - it was whilst looking for a C# equivalent that I found LinFu).
FURTHER EDIT: TO clarify what I mean by composition/delegation and mixin.
public class Person : NEOtherBase, IName, IAge
{
public Person()
{
}
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Name "Mixin" - you'd need this code in any object that wanted to
//use the NameObject to implement IName
private NameObject _nameObj = new NameObject();
public string Name
{
get { return _nameObj.Name; }
set { _nameObj.Name = value; }
}
//--------------------
//Age "Mixin" you'd need this code in any object that wanted to
//use the AgeObject to implement IAge
private AgeObject _ageObj = new AgeObject();
public int Age
{
get { return _ageObj.Age; }
set { _ageObj.Age = value; }
}
//------------------
}
public interface IName
{
string Name { get; set; }
}
public class NameObject : IName
{
public NameObject()
{}
public NameObject(string name)
{
_name = name;
}
private string _name;
public string Name { get { return _name; } set { _name = value; } }
}
public interface IAge
{
int Age { get; set; }
}
public class AgeObject : IAge
{
public AgeObject()
{}
public AgeObject(int age)
{
_age = age;
}
private int _age;
public int Age { get { return _age; } set { _age = value; } }
}
Imagine objects with many more properties, used in many more "subclasses" and you start to see the tedium. A code-gernation tool would actually be just fine...
So, LinFu....
The mixin example below is fine but I'd want to have an actual Person class (as above) - what's the LinFu-esque way of doing that? Or have I missed the whole point?
EDIT: I need to be able to do this with classes that are already subclassed.
DynamicObject dynamic = new DynamicObject();
IPerson person = null;
// This will return false
bool isPerson = dynamic.LooksLike<IPerson>();
// Implement IPerson
dynamic.MixWith(new HasAge(18));
dynamic.MixWith(new Nameable("Me"));
// Now that it’s implemented, this
// will be true
isPerson = dynamic.LooksLike<IPerson>();
if (isPerson)
person = dynamic.CreateDuck<IPerson>();
// This will return “Me”
string name = person.Name;
// This will return ‘18’
int age = person.Age;

Categories