force variables from superclass to be assigned (at compile time) - c#

I have a superclass which has a bunch of variables.
e.g.
string s1= ""; string s2= ""; string s3= "";
...etc
I'd like to guarantee that these variables get overridden (assigned something useful) in the subclass that inherits from this superclass, at compile time.
is there an elegent way of doing this?

Make all the constructors in the base class take them as parameters, and set them from those constructors:
protected BaseClass(string s1, string s2, string s3)
{
this.s1 = s1;
this.s2 = s2;
this.s3 = s3;
}
...
// Just for example
public DerivedClass(string x) : base("foo", "bar", x)
{
}
Hopefully they're private fields anyway, so the derived class couldn't set them directly anyway, right? :)

You cannot have virtual fields in C#. If you really need this, you could use Properties which you then override and give a default value in your subclass.
public class A
{
private string s1;
public virtual string S1
{
get { return this.s1; }
}
}
public class B : A
{
private string myString = "default";
public override string S1
{
get
{
return this.myString;
}
}
}

Related

C# How could a superclass return back 3 possible types without casting from the calling class

Before I begin, I want to state I realize this isn't the ideal way of doing this. However the calling class can't be changed according to the rules of the assignment. I have tried to understand and find a solution to this problem, but I have had no luck.
Below there is 1 superclass,TreeMangement (There can only be 1 superclass for these subclasses). There are 3 subclasses(apple, orange and banana). The "find" method must be in the TreeMangement superclass. I am not allowed to override the "find" method. With the current code, I will get a casting error in the calling class. It will state that a TreeMangement can't implicity be casted into a AppleTree,OrangeTree or BananaTree.
Now my question is, am I able to somehow pass the correct type back to the calling class no matter what type (Apple,Banana,Orange) is calling it, without casting in the calling class? If so, how? If not, references so I know there is absolutely no way of doing it.
public class TreeMangement
{
public string id {get; set;}
public TreeMangement()
{
id = this.GetType().Name+"|"+Guid.NewGuid();
}
public static TreeMangement Find(string idIn)
{
string type = idIn.Split('|')[0];
return Functions.GetObj(idIn, GetFilePath(type), type); //returns back the right type
}
}
public class AppleTree:TreeMangement
{
public string Name;
}
public class OrangeTree:TreeMangement
{
public string Name;
}
public class BananaTree:TreeMangement
{
public string Name;
}
///////Calling class////
AppleTree savedAppleTree = AppleTree.Find("SomeValidID");
OrangeTree savedOrangeTree = OrangeTree.Find("SomeValidID");
BananaTree savedBananaTree = BananaTree.Find("SomeValidID");
You can change the superclass to a generic superclass like this:
public class TreeMangement<T>
where T: class
{
...
public static T Find(string idIn)
{
return ... as T;
}
}
Now you are able to specifiy the return type in your subclasses like
public class AppleTree:TreeMangement<AppleTree>
{
public string Name;
}
public class OrangeTree:TreeMangement<OrangeTree>
{
public string Name;
}
public class BananaTree:TreeMangement<BananaTree>
{
public string Name;
}
This way your 3 find calls will compile just fine as the Find() call will return the correct type:
var savedAppleTree = AppleTree.Find("SomeValidID");
var savedOrangeTree = OrangeTree.Find("SomeValidID");
var savedBananaTree = BananaTree.Find("SomeValidID");

Implicit operators and class hierarchies

I have the following class hierarchy.
public abstract class ResourceBase { }
public abstract class WebResourceBase : ResourceBase {
public ResourceBase LocalPath { get; set; }
public ResourceBase FtpPath { get; set; }
}
public class JavaScript : WebResourceBase { }
What I would like to do is have a declaration like so.
new JavaScript() {
LocalPath = "/path/goes/here/1.js",
FtpPath = "ftp://path/goes/here/1.js"
}
The obvious answer here would be to use implicit operators but the problem is that I want to assign a derived type to those properties which is the same as the declared type so LocalPath and FtpPath would be of type JavaScript.
I'd like my solution to be more flexible than what I have at the moment. This code just makes my skin crawl. Was hoping there was a way using reflection and I have tried looking for information using the StackTrace class but no luck. Any help would be appreciated. Thanks.
public abstract class ResourceBase {
public static implicit operator ResourceBase(string path) {
if (path.EndsWith(".js"))
return new JavaScript(path);
// etc...
}
}
This assumes that WebResourceBase is actually meant to inherit ResourceBase.
You won't be able to make the implicit operator look much nicer, unfortunately - generics won't work here.
Alternative: Generics to constrain ResourceBase
Now that I've re-read it and understand what you're after, one option is to amend your classes to include a generic parameter referencing derived classes (sort of like a self-reference):
public abstract class ResourceBase
{ }
public abstract class WebResourceBase<T> : ResourceBase
where T : WebResourceBase<T>
{
public T LocalPath { get; set; }
public T FtpPath { get; set; }
}
public class JavaScript : WebResourceBase<JavaScript>
{
}
Then you will see that in JavaScript, the properties LocalPath and FtpPath are now of type JavaScript also.
Now your assignment will only accept JavaScript types:
new JavaScript()
{
LocalPath = new JavaScript("/path/goes/here/1.js"),
FtpPath = new JavaScript("ftp://path/goes/here/1.js")
}
The benefit of this approach is it will constrain the base properties to be of the current type or more derived, not less derived.
Alternative: Explicit parsing instead of implicit operator
If you need to leave the LocalPath and FtpPath variables as ResourceBase, or otherwise cannot use generics here, your implicit operator will start to get confusing. Better to provide something explicit like a static method:
new JavaScript()
{
LocalPath = JavaScript.Parse("/path/goes/here/1.js"),
FtpPath = JavaScript.Parse("ftp://path/goes/here/1.js")
}
class JavaScript
{
public static ResourceBase Parse(string s)
{
if (path.EndsWith(".js"))
return new JavaScript(path);
throw new Exception();
}
}
Alternative: Class hierarchy parsing instead of implicit operator
Bake the concept of consuming strings into the types via constructors and make the properties public read-only:
public abstract class ResourceBase
{ }
public abstract class WebResourceBase
{
public ResourceBase LocalPath { get; private set; }
public ResourceBase FtpPath { get; private set; }
protected abstract ResourceBase ParseLocalPath(string s);
protected abstract ResourceBase ParseFtpPath(string s);
}
public class JavaScript : WebResourceBase<JavaScript>
{
protected override ResourceBase ParseLocalPath(string s)
{
// etc.
}
protected override ResourceBase ParseFtpPath(string s)
{
// etc.
}
}
To be honest, most of this seems a little overkill just to get two properties set as a particular type from a string, you have loads of options - even the implicit operator will work.
Pick the one that is easiest to understand. Operator overloading tends to be somewhat hidden unless you go digging for it.
I too assume that WebResourceBase is supposed to inherit from ResourceBase
Have a protected mapping mechanism on the base class that derived classes can subscribe themselves to:
public abstract class ResourceBase
{
// Records how to make a ResourceBase from a string,
// on a per-extension basis
private static Dictionary<string, Func<string, ResourceBase>> constructorMap
= new Dictionary<string, Func<string, ResourceBase>>();
// Allows a derived type to subscribe itself
protected static void Subscribe(
string extension,
Func<string, ResourceBase> ctor)
{
if (constructorMap.ContainsKey(extension))
throw new Exception("nuh uh");
constructorMap.Add(extension, ctor);
}
// Given a string, finds out who has signed up to deal with it,
// and has them deal with it
public static implicit operator ResourceBase(string s)
{
// Find a matching extension
var matches = constructorMap.Where(kvp => s.EndsWith(kvp.Key)).ToList();
switch (matches.Count)
{
case 0:
throw new Exception(
string.Format("Don't know how to make {0} into a ResourceBase",
s));
case 1:
return matches.Single().Value(s);
default:
throw new Exception(string.Format(
"More than one possibility for making {0} into a ResourceBase",
s));
}
}
}
The intermediate type is largely unchanged, but with some type checking that I can't work out how to enforce at compile time:
public abstract class WebResourceBase : ResourceBase
{
private ResourceBase localPath;
public ResourceBase LocalPath
{
get { return localPath; }
set
{
if (value.GetType() != GetType())
{
throw new Exception("Naughty");
}
localPath = value;
}
}
private ResourceBase ftpPath;
public ResourceBase FtpPath
{
get { return ftpPath; }
set
{
if (value.GetType() != GetType())
{
throw new Exception("Naughty");
}
ftpPath = value;
}
}
}
The concrete types look like this:
public class JavaScript : WebResourceBase
{
public JavaScript()
{
}
private JavaScript(string s)
{
}
static JavaScript()
{
Subscribe("js", s => (ResourceBase)new JavaScript(s));
}
}
Usage is as you specified:
var js = new JavaScript
{
LocalPath = "hello.js",
FtpPath = "hello.js"
};
Note that despite the ResourceBase in the signature of constructorMap and Subscribe, after the above statement LocalPath and FtpPath are JavaScript objects.
I would just add an extra layer of indirection to the process (it's amazing how often that's a good answer for design questions ;) ).
I would either add a new constructor that takes two string parameters, add two additional string properties, or both. (I'll assume you're just adding two new string properties from here on; you can extrapolate from there.)
If you add a new property: JavaScriptLocalPath it can, in it's set method, convert the string into a derived type of ResourceBase specific to JavaScript and the set the LocationPath property using that result. I assume it's get method can also extract that string out of the ResourceBase (so that you don't need to bother storing the string as well).
Here's my idea:
public abstract class WebResourceBase {
public ResourceBase LocalPath { get; set; }
public ResourceBase FtpPath { get; set; }
protected abstract ResourceBase ConvertFromString(string path);
public string LocalPathStr { set { LocalPath = ConvertFromString(value); } }
public string FtpPathStr { set { FtpPath = ConvertFromString(value); } }
}
Could probably be improved.

initializing variables in c#

I'm a bit confused.
I have the following code:
public class MyClass
{
public string DoSomething(string TheString)
{
int TheID;
string TheString = "";
}
}
This works fine; it compiles. However, why doesn't this work?
public class MyClass
{
public string DoSomething(string TheString)
{
private int TheID {get;set;}
private string TheString {get;set;}
}
}
I want to make these variables private. What do I need to change?
Private variables are only valid at the class level:
public class MyClass {
private int TheID {get;set;}
private string TheString {get;set;}
public string DoSomething(string TheString) {
}
}
Variables defined inside a method are local in scope and they only exist inside that method. Nothing outside the method can access them. It makes no sense to declare a local variable as private.
They are scoped inside the method - you can't access them outside of it. You can think of them as being private.

Overriding constants in derived classes in C#

In C# can a constant be overridden in a derived class? I have a group of classes that are all the same bar some constant values, so I'd like to create a base class that defines all the methods and then just set the relevant constants in the derived classes. Is this possible?
I'd rather not just pass in these values to each object's constructor as I would like the added type-safety of multiple classes (since it never makes sense for two objects with different constants to interact).
It's not a constant if you want to override it ;). Try a virtual read-only property (or protected setter).
Read-only property:
public class MyClass {
public virtual string MyConst { get { return "SOMETHING"; } }
}
...
public class MyDerived : MyClass {
public override string MyConst { get { return "SOMETHINGELSE"; } }
}
Protected setter:
public class MyClass {
public string MyConst { get; protected set; }
public MyClass() {
MyConst = "SOMETHING";
}
}
public class MyDerived : MyClass {
public MyDerived() {
MyConst = "SOMETHING ELSE";
}
}
Unfortunately constants cannot be overridden as they are not virtual members. Constant identifiers in your code are replaced with their literal values by the compiler at compile time.
I would suggest you try to use an abstract or virtual property for what you would like to do. Those are virtual and as such can (must, in the case of an abstract property) be overridden in the derived type.
Constants marked with const cannot be overridden as they are substituted by the compiler at compile time.
But regular static fields assigned to constant values can. I've had such a case just now:
class Columns
{
public static int MaxFactCell = 7;
}
class Columns2 : Columns
{
static Columns2()
{
MaxFactCell = 13;
}
}
If I just redefined the MaxFactCell field in the derived class instead, polymorphism wouldn't work: code using Columns2 as Columns would not see the overriding value.
If you need to restrict write (but not read) access to the field, using readonly would prohibit redefining it in Columns2. Make it a property instead, that's slightly more code:
class Columns
{
static Columns()
{
MaxFactCell = 7;
}
public static int MaxFactCell { get; protected set; }
}
class Columns2 : Columns
{
static Columns2()
{
MaxFactCell = 13;
}
}
Edit: This can have unexpected behaviour, see Shai Petel's remark below.
You can hide the inherited constant in a derived class by declaring the new constant new. I'm not sure this is a good practice, though.
class A
{
protected const int MyConst = 1;
}
class B : A
{
new private const int MyConst = 2;
}
to Work off dten + Tracker1's answer but updated for c# 6
public class MyClass {
public virtual string MyConst =>"SOMETHING";
}
...
public class MyDerived : MyClass {
public override string MyConst =>"SOMETHING ELSE";
}
You can force derived classes to have a value for a constant (well, a read-only property)
Make an interface containing a read-only property.
Put that interface on the base class.
Example:
public interface IHasConstant
{
string MyConst { get; }
}

Initialize base class in .NET

How do I go about if I need to initialize an object's base with existing object? For example, in this scenario:
public class A
{
public string field1;
public string field2;
}
public class B : A
{
public string field3;
public void Assign(A source)
{
this.base = source; // <-- will not work, what can I do here?
}
}
Assign() method can, obviously assign values to the base class field-by-field, but isn't there a better solution? Since class B inherits from A, there must be a way to just assign A to the B.base
In C++ this would be a trivial thing to do, but I can't seem to grasp how to do this in .NET
Unfortunately base is readonly.
[Edit]
Well perhaps not so unfortunate. The relationship between a base class and a child class is IS-A not HAS-A. By allowing a child class to change the instance of the base class you are allowing the child class to change its own reference since it IS-A base class. If you truly need this functionality then I would suggest you change your inheritance model to reflect what you truly want to do.
Something like this:
public class A
{
public string field1;
public string field2;
}
public class B
{
public string field3;
public A a;
public void Assign(A source)
{
this.a = source;
}
}
seems more appropriate and has clearer meaning and functionality.
public Assign(A a)
{
foreach (var prop in typeof(A).GetProperties())
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(a, null),null);
}
}
Basically, it uses reflection to get all the properties of the base and assign the values of this, to all the values that exist in A.
EDIT: To all you naysayers out there, I quickly tested this now with a base class that had 100 integer variables. I then had this assign method in a subclass. It took 46 milliseconds to run. I don't know about you, but I'm totally fine with that.
While there are many excellent answers here, I think the proper way to do this is by chaining the constructors:
public class A
{
public string field1;
public string field2;
public A(string field1, string2 field2)
{
this.field1 = field1;
this.field2 = field2;
}
}
public class B : A
{
public string field3;
public B(string field1, string2 field2, string field3)
: base(field1, field2)
{
this.field3 = field3;
}
}
No, the syntax you are trying is not possible. In C# .NET you need to do:
public void Assign(A source) {
field1 = source.field1;
field2 = source.field2;
}
Is the intent that these fields will be initialized once during object construction, or could "Assign" be called multiple times during an object's lifetime? If the latter, you can disregard the rest of this :)
Andrew's distinction between IS-A and HAS-A is an important one; if the relationship really is a HAS-A, his composition solution is the way to go.
If an IS-A relationship makes more sense (and you are able to modify A), a copy constructor might be a good idea:
public class A
{
public string field1;
public string field2;
public A(A copyFrom)
{
this.field1 = copyFrom.field1;
this.field2 = copyFrom.field2;
}
}
public class B : A
{
public string field3;
public B(A source)
: base(source)
{
}
}
You end up having to copy each of A's properties, but the responsibility for doing so resides in A where it belongs.
Why would you need to? By declaring a new B, the CLR automatically calls the constructors for both classes.
B myB = new B();
B new has the fields of both classes. However, you should declare them with an initializer unless you like nulls:
public string field1 = "";
public string field2 = string.Empty;
I hope I'm not the only one who thinks swapping out your base class is a bad design pattern. Another approach is to replace inheritance with composition:
public class A
{
public string Field1 { get; set; }
public string Field2 { get; set; }
}
public class B
{
public A A { get; set; }
public string Field3 { get; set; }
public B(A a) { this.A = a; }
}
Now its trivial to write something like this:
B b = new B ( new A { Field1 = "hello", Field2 = "world" } );
b.A = new A { Field1 = "hola", Field2 = "luna" };
Wrong question.
You're obviously abusing inheritance here.
Try to refactor it, so that you keep a reference to A as a member field.
If you need polymorphism, consider having common base class or better yet - an interface.
[TestMethod]
public void TestMethod()
{
A a = new A();
a.field1 = "test";
string xml = Serialize(a);
xml = xml.Replace("A", "B");
B b = Deserialize(xml);
Assert.AreEqual("test", b.field1);
}
public string Serialize(A a)
{
System.IO.StreamReader streamReader = null;
System.IO.MemoryStream memoryStream = null;
try
{
memoryStream = new System.IO.MemoryStream();
XmlSerializer serializer = new XmlSerializer(typeof(A));
serializer.Serialize(memoryStream, a);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
streamReader = new System.IO.StreamReader(memoryStream);
return streamReader.ReadToEnd();
}
finally
{
if ((streamReader != null))
{
streamReader.Dispose();
}
if ((memoryStream != null))
{
memoryStream.Dispose();
}
}
}
public static B Deserialize(string xml)
{
System.IO.StringReader stringReader = null;
try
{
stringReader = new System.IO.StringReader(xml);
XmlSerializer serializer = new XmlSerializer(typeof(B));
return ((B)(serializer.Deserialize(System.Xml.XmlReader.Create(stringReader))));
}
finally
{
if ((stringReader != null))
{
stringReader.Dispose();
}
}
}
According to MSDN, "base" can only be used for the following operations:
Call a method on the base class that has been overridden by another method.
Specify which base-class constructor should be called when creating instances of the derived class.

Categories

Resources