Setting a property in a derived class that points to a different field

Viewed 41

I'm wondering if there's a way to do this, and I don't quite understand why it's not working. Full disclosure, this is in Unity, so it may be something resolved in a later version of C#.

I have class Foo. Foo has a field and property:

MeshRenderer meshRenderer;
public MeshRenderer Renderer {get {return this.meshRenderer;} set {this.meshRenderer = value;}}

I have a derived class Bar. Bar has a field and property:

SkinnedMeshRenderer skinnedMeshRenderer;
public SkinnedMeshRenderer Renderer {get {return this.skinnedMeshRenderer;} set {this.skinnedMeshRenderer= value;}}

Foo has a method, Remesh() that sets:

this.Renderer.materials = SomeListOfMaterials.ToArray();

Bar, of course, inherits this method. Both MeshRenderer and SkinnedMeshRenderer have a public materials field that takes an array of materials. When I debug into the code, a call to Bar.Remesh() falls through to the Foo.Remesh() method as expected, and this.Renderer.materials is valid as expected, and SomeListOfMaterials is a list of materials, as expected. But it comes back with a null reference exception.

If I copy the Remesh() code verbatim into Bar (with the new modifier), it works fine. When it's falling through to Foo.Remesh(), I even checked that this is actually Bar (it is).

2 Answers

Edit I think I understand now:

In foo this.Renderer is the MeshRenderer and in bar this.Renderer is the SkinnedMeshRenderer, so when you call Remesh() from the base class its pulling the MeshRenderer but when you add Remesh() to Bar, this.Renderer calls skinnedMeshRenderer. I think you should just add Remesh() method to Bar as a overrided method as you are now working with a SkinnedMeshRenderer instead of a MeshRenderer.

this.Renderer.materials = SomeListOfMaterials.ToArray();

edit part two to keep code clean

foo

Renderer renderer;
public Renderer Renderer {get {return this.renderer;} set {this.renderer = value;}}

bar dont change renderer method, MeshRenderer and SkinnedMeshRenderer both derive renderer, so you should still be able to set a MeshRenderer in foo and a SkinnedMeshRenderer in bar, thus you can just keep Remesh() in foo and it will be valid without overriding in bar.

Bar.Renderer is shadowing Foo.Renderer, which property you access depends on the variable you access them through.

If they are supposed to be the same instance, then Bar should store its Renderer in the same base field;

public SkinnedMeshRenderer Renderer {get {return (SkinnedMeshRenderer)base.Renderer;} set {base.Renderer = value;}}
Related