Overloading constructors and methods seems messy, i.e. simply differentiating them by the order and number of parameters. Isn't there a way, perhaps with generics, to do this cleanly so that, even if you just have one parameter (e.g. string idCode / string status) you could still differentiate them?
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TheForm tf1 = new TheForm("online", DateTime.Now);
TheForm tf2 = new TheForm(DateTime.Now, "form1");
}
}
public class TheForm
{
public TheForm(string status, DateTime startTime)
{
//...
}
public TheForm(DateTime startTime, string idCode)
{
//...
}
}
}
If you need that many overloads, perhaps your types are handling too much (see Single Responsibility Principle). Personally I rarely need more than one or a few constructors.
You could consider having a Fluent Builder for the class instead, although it's more work. This would allow you to write something like this:
var form = new TheFormBuilder().WithStatus("foo").WithStartTime(dt).Build();
It's more explicit, but not necessary better. It's definitely more work.
In C# 4, you can optionally write the parameter names when you invoke the constructor:
var form = new TheForm(status: "Foo", startTime: dt);
The new object initialization feature of .NET 3.0 is more flexible than an overloaded constructor. Here is a simple example:
public class Item
{
public string Name {get; set;}
public int Index {get; set;}
public string Caption {get; set;}
}
As it is written now, we can do the following in code:
var x = new item {Name=”FooBar”};
var x = new item {Name=”FooBar”, Index=”1”, Caption=”Foo Bar”};
I would only add an overloaded constructor to the class Item if I want to add functionality during property initialization. For example:
public class Item
{
public Item() {}
public Item(string name)
{
Name = name;
Caption = name; //defaulting name to caption
}
public Item(string name, int index) : this(name)
{
Index = index;
}
public Item(string name, int index, string caption) : this(name, int)
{
Caption = caption;
}
public string Name {get; set;}
public int Index {get; set;}
public string Caption {get; set;}
}
Note: If this was a child class, I could have chained to a parent constructor with the “base” keyword.
If I am writing a “configuration” type of class, I use Fluent Methods in place of Overloaded constructors.
For example, if I added these methods to the Item class:
public Item WithName(string name)
{
Name = name;
return this;
}
public Item WithIndex(int index)
{
Index = index;
return this;
}
public Item WithCaption(string caption)
{
Caption = caption;
return this;
}
I could write code like this:
var x = new Item().WithName(“FooBar”).WithIndex(“99”).WithCaption(“Foo Bar”);
The only way I can think of to differentiate the construction with a single parameter of a given type is to use a non-instance factory method, either on the type itself or in a factory class.
e.g. (on the type itself)
(untested)
public class TheForm
{
public static TheForm CreateWithId(string idCode)
{
}
public static TheForm CreateWithStatus(string status)
{
}
}
Before Fluent builders we sometimes managed to get around with parameter objects or setup objects:
public class FormSetup {
public string Status ...
public string Id ...
}
var frm = new MyForm(new FormSetup { Status = "Bla", ... });
Constructor Forwarding!
Use helper initialization classes to communicate the semantics of your overloads.
So, for instance, define
public class TheForm
{
public class TheForm(ById initializer)
{
//...
}
public class TheForm(ByStatus initializer)
{
//...
}
// ...
public class ById
{
public ById(DateTime startTime, string idCode)
// ...
}
public class ByStatus
{
public ByStatus(string status, DateTime startTime)
// ...
}
}
However, prefer using classes which are more generally usable if you can, not just for initalialization. You may want to factor your classes in a different way instead. I sense the possibility of a code smell: does your TheForm class contain too much business logic? Might you want to split out an MVC Controller, for instance?
In C# (like in many other programming languages) in this case you should use Factory Methods. Something like this:
class TheForm
{
public static TheForm CreateFromId(string idCode);
public static TheForm CreateFromStatus(string status);
}
or fiction parameters:
class TheForm
{
public TheForm(string idCode, int);
public TheForm(string status);
}
Or you can use Eiffel ;):
class THE_FORM create
make_from_id, make_from_status
feature
...
end
We use properties instead of overloading constructors, it's quite clean and easy to implement:
public class x {
public string prop1 {get;set;}
public DateTime prop2 {get;set;}
...
}
and then fill just the properties you need at instantiation time (and/or later)
var obj = new x() {
prop1 = "abc",
prop2 = 123
};
The benefit with this is it works with .Net 3.5 and makes it really clear what is being set. (as opposed to var obj = new x("abc", 123, true, false, ... etc) where you have to guess the meaning of each value, which can get really hairy when there are many overloads)
Here's an example:
Timespan.FromMilliseconds(double)
Timespan.FromSeconds(double)
Timespan.FromMinutes(double)
Timespan.FromHours(double)
Timespan.FromDays(double)
Isn't this where inheritence comes in?
Just have TheForm as a base class and then TheFormWithID and TheFormWithStatus child classes.
Have their constructors take string ID and string Status respectively passing back the DateTime value to the base class.
I haven't got any coding tools infront of me so please excuse the syntax. I'm sure that you'll figure it out.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
TheForm tf1 = new TheFormWithStatus(DateTime.Now, "online");
TheForm tf2 = new TheFormWithID(DateTime.Now, "form1");
}
}
public class TheForm
{
public TheForm(DateTime startTime)
{
//...
}
}
public class TheFormWithID : TheForm
{
public TheFormWithID (DateTime startTime, string idCode) : TheForm (startTime)
{
//...
}
}
public class TheFormWithStatus : TheForm
{
public TheFormWithStatus (DateTime startTime, string status) : TheForm (startTime)
{
//...
}
}
}
Or have TheForm as an abstract class.
Whether you're talking about constructors or not, overloading's pretty limited, and when you start to run up against its limits, that's a hint that it's not the right tool for the job.
It's worth looking at a well-designed API that uses overloading to get a sense of what kind of job the tool is good for. XmlReader.Create is a good example: It supports twelve different overloads. Twelve! And yet, it's actually completely sensible: when you look at them all, they boil down to what would, in Python, be a single calling signature with optional parameters:
XmlReader.Create(input [, settings [, parser_context]])
input, to this method, can be a string containing a URL or filename, a TextReader, or a Stream. But irrespective of its data type, it's still fundamentally the same thing: the source of the data that the XmlReader is going to read.
Now let's look at your case. Forget about data types for a moment. There's clearly some functional difference between a status and an idCode in your application. Your form is going to behave one way if it's given a status and another if it's given an idCode. The API that you're proposing conceals this functional difference. It should be illuminating it.
I would first consider the simplest possible approach, which uses no overloads at all:
TheForm(string idCode, string status)
Make your constructor throw an exception if both values are provided (or if both are null). Note that they're mutually exclusive in the documentation. Call it a day.
My second choice would be:
enum FormType
{
IdCode,
Status
};
TheForm(FormType type, string data)
This is less concise, but it has the very great merit of making the fact that this method supports multiple mutually-exclusive modes explicit.
I called that enum FormType because it seemed like a sensible name, given what I know so far, and the fact that this method's a constructor. But whenever you contemplate creating an enum to determine the type of an instance, you should at least consider the possibility that you should really be creating a type to determine the type of an instance:
class TheFormWhatUsesIdCode : TheForm {...}
class TheFormWhatUsesStatus : TheForm {...}
The functional difference between idCode and status probably relates to a functional difference between a form instantiated with idCode and a form instantiated with status. And that strongly suggests that they should be subclasses.
In all of this analysis, I've never once considered the possibility of doing what you actually asked for, which is to provide multiple overloads. I don't think overloading is the right tool for this job. If idCode were an int and status were a string I still wouldn't think that overloading were the right tool for this job, though I probably wouldn't have ended up noticing it until I had a lot of code I needed to refactor.
I am not getting what "messy" you found in multiple constructors. I felt the static methods for returning an instance of the object also a probable alternate.
But, if somebody want to have the fancy of a single constructor and still have different implementations, we can think of passing an object derived from some interface as the input to the constructor and might check the type of the input to create an instance. This is kind of an abstract factory in this case.
In one place we have a class like the following:
using System;
namespace MyApplication
{
class Program
{
static void Main(string[] args)
{
base1 t1 = new type1();
class1 c1 = new class1(t1);
base1 t2 = new type2();
class1 c2 = new class1(t2);
//.....
}
}
public class class1
{
public class1(base1 mytype)
{
switch(mytype.type)
case mytype.types.type1
return createObjectOftype1();
case mytype.types.type2
return createObjectOftype2();
case mytype.types.type3
return createObjectOftype3();
}
public class1 createObjectOftype1()
{
//....
}
public class1 createObjectOftype2()
{
//...
}
public class1 createObjectOftype2()
{
//...
}
}
public class base1
{
publlic Enum Types {0 "type1",....
}
public class type1:base1
{
//.....
}
public class type2:base1
{
//.....
}
}
I personally dont like the idea of other classes being able to set my properties
so this allows my properties to be protected or private, but still have alot of the functionality described by other answers:
public class FooSettings
{
public bool Prop1 { get; set; }
public bool Prop2 { get; set; }
public TimeSpan Prop3 { get; set; }
public FooSettings()
{
this.Prop1 = false;
this.Prop2 = false;
this.Prop3 = new TimeSpan().ExtensionMethod(CustomEnum.Never);
}
public FooSettings BoolSettings
(bool incomingFileCacheSetting, bool incomingRuntimeCacheSetting)
{
this.Prop1 = incomingFileCacheSetting;
this.Prop2 = incomingRuntimeCacheSetting;
return this;
}
public FooSettings Prop3Setting
(TimeSpan incomingCustomInterval)
{
this.Prop3 = incomingCustomInterval;
return this;
}
public FooSettings Prop3Setting
(CustomEnum incomingPresetInterval)
{
return this.Prop3Setting(new TimeSpan().ExtensionMethod(CustomEnum.incomingPresetInterval));
}
}
public class Foo
{
public bool Prop1 { get; private set; }
public bool Prop2 { get; private set; }
public TimeSpan Prop3 { get; private set; }
public CallTracker
(
FooSettings incomingSettings
)
{
// implement conditional logic that handles incomingSettings
}
}
could then be consumed as:
FooSettings newFooSettings = new FooSettings {Prop1 = false, Prop2 = true}
newFooSettings.Prop3Setting(new TimeSpan(3,0,0));
Foo newFoo = new Foo(newFooSettings)
or
FooSettings newFooSettings = new FooSettings()
.BoolSettings(false, true)
.Prop3Setting(CustomEnum.Never)
Foo newFoo = new Foo(newFooSettings)
obviously a bit overkill for a simple class, but it gives alot of control over the types of data that can be funneled down to a single property, IE: TimeSpan can be parsed from a custom enum type using an extension method
Related
Is there an easy way to make an instance immutable?
Let's do an example, I have a class holding a lots of data fields (only data, no behavior):
class MyObject
{
// lots of fields painful to initialize all at once
// so we make fields mutable :
public String Title { get; set; }
public String Author { get; set; }
// ...
}
Example of creation:
MyObject CreationExample(String someParameters)
{
var obj = new MyObject
{
Title = "foo"
// lots of fields initialization
};
// even more fields initialization
obj.Author = "bar";
return obj;
}
But now that I have fully created my object, I don't want the object to be mutable anymore (because the data consumer will never need to change the state), so I would like something like that List.AsReadOnly:
var immutableObj = obj.AsReadOnly();
But if I want this behavior, I need to make another class that have exactly the same fields but without setter.
So is there any automatic way to generate this immutable class ? Or another way to allow mutability during creation but immutable once initialized ?
I know that fields can be marked as "readonly", but the object will be initialized outside of the class, and passing all fields as constructor parameters seems like a bad idea (too much parameters).
No, there is no easy way to make any type immutable, especially not if you want "deep" immutability (i.e. where no mutable object can be reached through the immutable object). You will have to explicitly design your types to be immutable. The usual mechanisms to make types immutable are these:
Declare (property-backing) fields readonly. (Or, starting with C# 6 / Visual Studio 2015, use read-only auto-implemented properties.)
Don't expose property setters, only getters.
In order to initialize (property-backing) fields, you must initialize them in the constructor. Therefore, pass the (property) values to the constructor.
Don't expose mutable objects, such as collections based on mutable-by-default types (like T[], List<T>, Dictionary<TKey,TValue>, etc.).
If you need to expose collections, either return them in a wrapper that prevents modification (e.g. .AsReadOnly()), or at the very least return a fresh copy of the internal collection.
Use the Builder pattern. The following example is too trivial to do the pattern justice, because it's usually recommended in cases where non-trivial object graphs need to be created; nevertheless, the basic idea is something like this:
class FooBuilder // mutable version used to prepare immutable objects
{
public int X { get; set; }
public List<string> Ys { get; set; }
public Foo Build()
{
return new Foo(x, ys);
}
}
class Foo // immutable version
{
public Foo(int x, List<string> ys)
{
this.x = x;
this.ys = new List<string>(ys); // create a copy, don't use the original
} // since that is beyond our control
private readonly int x;
private readonly List<string> ys;
…
}
Hmm I will enumerate my first thought on this...
1. Use internal setters if your only worry is manipulation outside of your assembly. internal will make your properties available to classes in the same assembly only. For example:
public class X
{
// ...
public int Field { get; internal set; }
// ...
}
2. I don't agree that it's necessarily a bad idea to have lots of parameters in your constructor.
3. You could generate another type at runtime that is a read-only version of your type. I can elaborate on this, but personally I think this is overkill.
Best, Iulian
As another solution you can use Dynamic Proxy. Alike approach was used for Entity Framework http://blogs.msdn.com/b/adonet/archive/2009/12/22/poco-proxies-part-1.aspx. Here is example how you can do it using Castle.DynamicProxy framework. This code is based on original example from Castle Dynamic proxy (http://kozmic.net/2008/12/16/castle-dynamicproxy-tutorial-part-i-introduction/)
namespace ConsoleApplication8
{
using System;
using Castle.DynamicProxy;
internal interface IFreezable
{
bool IsFrozen { get; }
void Freeze();
}
public class Pet : IFreezable
{
public virtual string Name { get; set; }
public virtual int Age { get; set; }
public virtual bool Deceased { get; set; }
bool _isForzen;
public bool IsFrozen => this._isForzen;
public void Freeze()
{
this._isForzen = true;
}
public override string ToString()
{
return string.Format("Name: {0}, Age: {1}, Deceased: {2}", Name, Age, Deceased);
}
}
[Serializable]
public class FreezableObjectInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
IFreezable obj = (IFreezable)invocation.InvocationTarget;
if (obj.IsFrozen && invocation.Method.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase))
{
throw new NotSupportedException("Target is frozen");
}
invocation.Proceed();
}
}
public static class FreezableObjectFactory
{
private static readonly ProxyGenerator _generator = new ProxyGenerator(new PersistentProxyBuilder());
public static TFreezable CreateInstance<TFreezable>() where TFreezable : class, new()
{
var freezableInterceptor = new FreezableObjectInterceptor();
var proxy = _generator.CreateClassProxy<TFreezable>(freezableInterceptor);
return proxy;
}
}
class Program
{
static void Main(string[] args)
{
var rex = FreezableObjectFactory.CreateInstance<Pet>();
rex.Name = "Rex";
Console.WriteLine(rex.ToString());
Console.WriteLine("Add 50 years");
rex.Age += 50;
Console.WriteLine("Age: {0}", rex.Age);
rex.Deceased = true;
Console.WriteLine("Deceased: {0}", rex.Deceased);
rex.Freeze();
try
{
rex.Age++;
}
catch (Exception ex)
{
Console.WriteLine("Oups. Can't change that anymore");
}
Console.WriteLine("--- press enter to close");
Console.ReadLine();
}
}
}
I would suggest having an abstract base type ReadableMyObject along with derived types MutableMyObject and ImmutableMyObject. Have constructors for all the types accept a ReadableMyObject, and have all the property setters for ReadableMyObject call an abstract ThrowIfNotMutable method before updating their backing field. Additionally, have ReadableMyObject support a public abstract AsImmutable() method.
Although this approach will require writing some boilerplate for each property of your object, that will be the extent of the required code duplication. The constructors for MutableMyObject and ImmutableMyObject will simply pass the received object to the base-class constructor. Class MutableMyObject should implement ThrowIfNotMutable to do nothing, and AsImmutable() to return new ImmutableMyObject(this);. Class ImmutableByObject should implement ThrowIfNotMutable to throw an exception, and AsImmutable() to return this;.
Code which receives a ReadableMyObject and wants to persist its contents should call its AsImmutable() method and store the resulting ImmutableMyObject. Code which receives a ReadableMyObject and wants a slightly-modified version should call new MutableMyObject(theObject) and then modify that as required.
You kind of hinted at a way in your question, but I'm not sure if this is not an option for you:
class MyObject
{
// lots of fields painful to initialize all at once
// so we make fields mutable :
public String Title { get; protected set; }
public String Author { get; protected set; }
// ...
public MyObject(string title, string author)
{
this.Title = title;
this.Author = author;
}
}
Due to the constructor being the only way of manipulating your Author and Title, the class is in effect immutable after construction.
EDIT:
as stakx mentioned, I too am a big fan of using builders - especially because it makes unit testing easier. For the above class you could have a builder such as:
public class MyObjectBuilder
{
private string _author = "Default Author";
private string _title = "Default title";
public MyObjectBuilder WithAuthor(string author)
{
this._author = author;
return this;
}
public MyObjectBuilder WithTitle(string title)
{
this._title = title;
return this;
}
public MyObject Build()
{
return new MyObject(_title, _author);
}
}
This way you can construct your objects with default values, or override them as you please, but MyObject's properties can't be changed after construction.
// Returns a MyObject with "Default Author", "Default Title"
MyObject obj1 = new MyObjectBuilder.Build();
// Returns a MyObject with "George R. R. Martin", "Default Title"
MyObject obj2 = new MyObjectBuilder
.WithAuthor("George R. R. Martin")
.Build();
If you ever need to add new properties to your class, it's much easier to go back to your unit tests that consume from a builder rather than from a hardcoded object instantiation (i don't know what to call it, so pardon my terms).
Well, if you have too many parameters and you dont want to do constructors with parameters....here is an option
class MyObject
{
private string _title;
private string _author;
public MyObject()
{
}
public String Title
{
get
{
return _title;
}
set
{
if (String.IsNullOrWhiteSpace(_title))
{
_title = value;
}
}
}
public String Author
{
get
{
return _author;
}
set
{
if (String.IsNullOrWhiteSpace(_author))
{
_author = value;
}
}
}
// ...
}
Here's another option. Declare a base class with protected members and a derived class that redefines the members such that they are public.
public abstract class MyClass
{
public string Title { get; protected set; }
public string Author { get; protected set; }
public class Mutable : MyClass
{
public new string Title { get { return base.Title; } set { base.Title = value; } }
public new string Author { get { return base.Author; } set { base.Author = value; } }
}
}
Creating code will use the derived class.
MyClass immutableInstance = new MyClass.Mutable { Title = "Foo", "Author" = "Your Mom" };
But for all cases where immutability is expected, use the base class:
void DoSomething(MyClass immutableInstance) { ... }
I wrote the following console app to test static properties:
using System;
namespace StaticPropertyTest
{
public abstract class BaseClass
{
public static int MyProperty { get; set; }
}
public class DerivedAlpha : BaseClass
{
}
public class DerivedBeta : BaseClass
{
}
class Program
{
static void Main(string[] args)
{
DerivedBeta.MyProperty = 7;
Console.WriteLine(DerivedAlpha.MyProperty); // outputs 7
}
}
}
As this console app demonstrates, the MyProperty property exists once for all instances of BaseClass. Is there a pattern to use which would allow me to define a static property which will have allocated storage for each sub-class type?
Given the above example, I would like all instances of DerivedAlpha to share the same static property, and all instances of DerivedBeta to share another instance of the static property.
Why am I trying to do this?
I am lazily initializing a collection of class property names with certain attributes (via reflection). The property names will be identical for each derived class instance, so it seems wasteful to store this in each class instance. I can't make it static in the base class, because different sub-classes will have different properties.
I don't want to replicate the code which populates the collection (via reflection) in each derived class. I know that one possible solution is to define the method to populate the collection in the base class, and call it from each derived class, but this is not the most elegant solution.
Update - Example of what I'm doing
At Jon's request, here's an example of what I'm trying to do. Basically, I can optionally decorate properties in my classes with the [SalesRelationship(SalesRelationshipRule.DoNotInclude)] attribute (there are other attributes, this is just a simplified example).
public class BaseEntity
{
// I want this property to be static but exist once per derived class.
public List<string> PropertiesWithDoNotInclude { get; set; }
public BaseEntity()
{
// Code here will populate PropertiesWithDoNotInclude with
// all properties in class marked with
// SalesRelationshipRule.DoNotInclude.
//
// I want this code to populate this property to run once per
// derived class type, and be stored statically but per class type.
}
}
public class FooEntity : BaseEntity
{
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_A { get; set; }
public int? Property_B { get; set; }
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_C { get; set; }
}
public class BarEntity : BaseEntity
{
public int? Property_D { get; set; }
[SalesRelationship(SalesRelationshipRule.DoNotInclude)]
public int? Property_E { get; set; }
public int? Property_F { get; set; }
}
Desired end result
Accessing FooEntity.PropertiesWithDoNotInclude returns a List<string> of:
{
"Property_A",
"Property_C"
}
Accessing BarEntity.PropertiesWithDoNotInclude returns a List<string> of:
{
"Property_E"
}
Two possible approaches:
Use attributes; decorate each subclass with an attribute, e.g.
[MyProperty(5)]
public class DerivedAlpha
{
}
[MyProperty(10)]
public class DerivedBeta
{
}
That only works when they're effectively constants, of course.
Use a dictionary:
var properties = new Dictionary<Type, int>
{
{ typeof(DerivedAlpha), 5) },
{ typeof(DerivedBeta), 10) },
};
EDIT: Now that we have more context, Ben's answer is a really good one, using the way that generics work in C#. It's like the dictionary example, but with laziness, thread-safety and simple global access all built in.
Jon has a good solution as usual, although I don't see what good attributes do here, since they have to be explicitly added to every subtype and they don't act like properties.
The Dictionary approach can definitely work. Here's another way to do that, which explicitly declares that there will be one variable per subclass of BaseEntity:
class FilteredProperties<T> where T : BaseEntity
{
static public List<string> Values { get; private set; }
// or static public readonly List<string> Values = new List<string>();
static FilteredProperties()
{
// logic to populate the list goes here
}
}
The drawback of this is that it's rather difficult to pair with a GetType() call such as you might use in methods of BaseEntity. A Dictionary, or wrapper thereto which implements lazy population, is better for that usage.
I just recently needed this same thing and came across this question. I think Jon's and Fried's ideas to use a Dictionary are on the right track but don't quite hit what I was looking for so I thought I'd show my own complete and very easy to extend implementation.
public class TypeStaticProperty<T>
{
T _defaultValue;
Dictionary<Type, T> _values = new Dictionary<Type, T>();
public TypeStaticProperty(T defalutValue = default)
{
_defaultValue = defalutValue;
}
public T Get(object caller)
{
lock (_values)
{
if (_values.TryGetValue(caller?.GetType(), out T val))
return val;
else
return _defaultValue;
}
}
public void Set(object caller, T val)
{
lock (_values)
_values[caller?.GetType()] = val;
}
}
And to demonstrate:
class TestBaseClass
{
static TypeStaticProperty<int> _property = new TypeStaticProperty<int>();
public int Property
{
get => _property.Get(this);
set => _property.Set(this, value);
}
}
class TestClass1 : TestBaseClass
{
}
class TestClass2 : TestBaseClass
{
}
class Program
{
static void Main(string[] args)
{
TestClass1 test1a = new TestClass1();
TestClass1 test1b = new TestClass1();
test1a.Property = 1;
test1b.Property = 2;
TestClass2 test2a = new TestClass2();
TestClass2 test2b = new TestClass2();
test2a.Property = 3;
test2b.Property = 4;
Console.WriteLine($"test1a.Property = {test1a.Property}");
Console.WriteLine($"test1b.Property = {test1b.Property}");
Console.WriteLine($"test2a.Property = {test2a.Property}");
Console.WriteLine($"test2b.Property = {test2b.Property}");
}
}
Output:
test1a.Property = 2
test1b.Property = 2
test2a.Property = 4
test2b.Property = 4
So while you still need a class instance to access and set the property, the value will always be the same across all instances of that precise type. (This includes generics too; Foo<int> will be seen as a different type than Foo<string>). This has the huge advantage over Fried's example in that you don't need to know at compile time the precise type whose "static" value you're looking for when accessing or setting.
PS - For full disclosure, this was heavily inspired by the WPF source code, which uses a very similar pattern for DependencyProperty's and all kinds of other internal bells and whistles designed to improve performance and reduce memory footprint.
I've got a class defined like this:
public abstract class Uniform<T>
{
public abstract string GlslType { get; }
...
}
And then a subclass defined like this:
public class UniformInt : Uniform<int>
{
public override string GlslType
{
get { return "int"; }
}
}
And then a method somewhere else that looks like this:
public static string GetCode<T>()
{
var sb = new StringBuilder();
var type = typeof(T);
sb.AppendFormat("struct {0} {{\n", type.Name);
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach(var f in fields)
{
sb.AppendFormat(" {0} {1};\n", f.FieldType.GetProperty("GlslType").GetValue(???), f.Name);
}
...
}
I'm having trouble filling in the ???s. I believe GetValue expects an instance of the object, but I don't really care what instance it is because they all return the same value. And AFAIK there's no such thing as a public abstract static readonly value, so I have to use properties.
So what can I put in place of those ???s to get back "int" (assuming one the fields was a UniformInt).
As a side: How can I limit fields to only field types that inherit Uniform<>?
You need an instance of UniformInt in order to get the value of a non-static property:
UniformInt someUniformInt = ...
f.FieldType.GetProperty("GlslType").GetValue(someUniformInt, null)
As a side: How can I limit fields to only field types that inherit Uniform?
bool isDerivesFromUniformOfInt = typeof(Uniform<int>)
.IsAssignableFrom(f.FieldType);
or if you don't know the type of T in advance:
bool isDerivesFromUniformOfT = typeof(Uniform<>)
.MakeGenericType(typeof(T))
.IsAssignableFrom(f.FieldType);
The problem is that since your property is not static the compiler doesn't know that they all return the same value. Since your UniformInt is not sealed, another user could inherit from it and override GlslType to return something else. Then UniformInt and all derived classes could be used for your GetCode<T>() method.
A static method would really be the best option. To make sure that you implement them on all classes (something you can't force because static methods can't be abstract) I would write a simple unit test that uses reflection to load all classes that inherit from Uniform<T> and check if they have the static property defined.
UPDATE
When thinking about how Attributes could help and after some experimenting I came up with the following. It definitely won't win a beauty contest but as a learning exercise it was helpful ;)
using System;
using System.Linq;
namespace StackOverflow
{
internal class StackOverflowTest
{
private static void Main()
{
string sInt = UniformInt.GlslType;
string sDouble = UniformDouble.GlslType;
}
}
public abstract class Uniform<B, T> // Curiously recurring template pattern
where B : Uniform<B, T>
{
public static string GlslType
{
get
{
var attribute = typeof(B).GetCustomAttributes(typeof(GlslTypeAttribute), true);
if (!attribute.Any())
{
throw new InvalidOperationException(
"The GslType cannot be determined. Make sure the GslTypeAttribute is added to all derived classes.");
}
return ((GlslTypeAttribute)attribute[0]).GlslType;
}
}
}
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
internal sealed class GlslTypeAttribute : Attribute
{
public string GlslType { get; private set; }
public GlslTypeAttribute(string glslType)
{
GlslType = glslType;
}
}
[GlslType("int")]
public class UniformInt : Uniform<UniformInt, int> // Curiously recurring template pattern
{
}
[GlslType("double")]
public class UniformDouble : Uniform<UniformDouble, double> // Curiously recurring template pattern
{
}
}
The GlslType is not static, so you need an object reference before you can access it's value. The subject of static properties in abstract classes has been covered extensively already, ie:
C#, implement 'static abstract' like methods
Can't define static abstract string property
Solution 1
Add static methods to all derived classes that return the GlslType. Nothing needs to be added to the base class. Can use unit testing + reflection to check for missing implementation. Suggested by Wouter de Kort.
Solution 2
Change Uniform<T> to make GlslType static:
public abstract class Uniform<T>
{
public static string GlslType { get { throw new NotImplementedException("Please override with \"new\" in derived class."); } }
...
}
Change UniformInt to "override" GlslType, keeping the static modifier:
public class UniformInt : Uniform<int>
{
public new static string GlslType
{
get { return "int"; }
}
}
Fill ??? with null, null:
sb.AppendFormat(" {0} {1};\n", f.FieldType.GetProperty("GlslType").GetValue(null,null), f.Name);
Solution 3
Use attributes instead. Something like:
[GlslType("int")]
public class UniformInt : Uniform<int>
{
}
Conclusion
All 3 of these solutions are pretty similar and seem to have the same drawbacks (can't enforce derived class to implement it). Throwing an exception via method 1 or 2 will help find errors quickly, or with 3 I can just skip over classes that don't have the attribute by modifying my fields condition.
I am trying to accomplish the following scenario that the generic TestClassWrapper will be able to access static properties of classes it is made of (they will all derive from TestClass). Something like:
public class TestClass
{
public static int x = 5;
}
public class TestClassWrapper<T> where T : TestClass
{
public int test()
{
return T.x;
}
}
Gives the error:
'T' is a 'type parameter', which is not valid in the given context.
Any suggestions?
You can't, basically, at least not without reflection.
One option is to put a delegate in your constructor so that whoever creates an instance can specify how to get at it:
var wrapper = new TestClassWrapper<TestClass>(() => TestClass.x);
You could do it with reflection if necessary:
public class TestClassWrapper<T> where T : TestClass
{
private static readonly FieldInfo field = typeof(T).GetField("x");
public int test()
{
return (int) field.GetValue(null);
}
}
(Add appropriate binding flags if necessary.)
This isn't great, but at least you only need to look up the field once...
Surely you can just write this:
public int test()
{
return TestClass.x;
}
Even in a nontrivial example, you can't override a static field so will always call it from your known base class.
Why not just return TestClass.x?
Generics do not support anything related to static members, so that won't work. My advice would be: don't make it static. Assuming the field genuinely relates to the specific T, you could also use reflection:
return (int) typeof(T).GetField("x").GetValue(null);
but I don't recommend it.
Another solution is to simply not make it static, and work with the new() constraint on T to instantiate the object. Then you can work with an interface, and the wrapper can get the property out of any class that implements that interface:
public interface XExposer
{
Int32 X { get; }
}
public class TestClass : XExposer
{
public Int32 X { get { return 5;} }
}
public class XExposerWrapper<T> where T : XExposer, new()
{
public Int32 X
{
get { return new T().X; }
}
}
In fact, you can change that to public static Int32 X on the TestClassWrapper and simply get it out as Int32 fetchedX = XExposerWrapper<TestClass>.X;
Though since whatever code calls this will have to give the parameter T those same constraints, the wrapper class is pretty unnecessary at this point, since that calling code itself could also just execute new T().X and not bother with the wrapper.
Still, there are some interesting inheritance models where this kind of structure is useful. For example, an abstract class SuperClass<T> where T : SuperClass<T>, new() can both instantiate and return type T in its static functions, effectively allowing you to make inheritable static functions that adapt to the child classes (which would then need to be defined as class ChildClass : SuperClass<ChildClass>). By defining protected abstract functions / properties on the superclass, you can make functions that apply the same logic on any inherited object, but customized to that subclass according to its implementations of these abstracts. I use this for database classes where the table name and fetch query are implemented by the child class. Since the properties are protected, they are never exposed, either.
For example, on database classes, where the actual fetching logic is put in one central abstract class:
public abstract class DbClass<T> where T : DbClass<T>, new()
{
protected abstract String FetchQuery { get; }
protected abstract void Initialize(DatabaseRecord row);
public static T FetchObject(DatabaseSession dbSession, Int32 key)
{
T obj = new T();
DatabaseRecord record = dbSession.RetrieveRecord(obj.FetchQuery, key);
obj.Initialize(record);
return obj;
}
}
And the implementation:
public class User : DbClass<User>
{
public Int32 Key { get; private set;}
public String FirstName { get; set;}
public String LastName { get; set;}
protected override String FetchQuery
{ get { return "SELECT * FROM USER WHERE KEY = {0}";} }
protected override void Initialize(DatabaseRecord row)
{
this.Key = DbTools.SafeGetInt(row.GetField("KEY"));
this.FirstName = DbTools.SafeGetString(row.GetField("FIRST_NAME"));
this.LastName = DbTools.SafeGetString(row.GetField("LAST_NAME"));
}
}
This can be used as:
User usr = User.FetchObject(dbSession, userKey);
This is a rather simplified example, but as you see, this system allows a static function from the parent class to be called on the child class, to return an object of the child class.
T is a type, not parameter or variable so you cannot pick any value from any members. Here is a sample code.
public class UrlRecordService
{
public virtual void SaveSlug<T>(T entity) where T : ISlugSupport
{
if (entity == null)
throw new ArgumentNullException("entity");
int entityId = entity.Id;
string entityName = typeof(T).Name;
}
}
public interface ISlugSupport
{
int Id { get; set; }
}
cjk and Haris Hasan have the most-correct answers to the question as asked. However in this comment the OP implies that he is after something else not quite possible in C#: a way to define a contract for a static member in a derived class.
There isn't a way to strictly define this, but it is possible to set up a pattern that may be implied by a base class (or interface); e.g.:
public class TestClass
{
private static int x;
public virtual int StaticX => x;
}
or if not intended to be used directly
public abstract class AbstractTestClass
{
public abstract int StaticX {get;}
}
or (my preference in this contrived example)
public interface ITest
{
int StaticX {get;}
}
Elsewhere, this pattern of a StaticXxx member may be (loosely) associated with implementations that should back the member with static fields (as in TestClass above).
What's kind of fun is that this can be (re)exposed as static by the generic wrapper, because generic statics are isolated to each type used.
public class TestClassWrapper<T> where T : ITest, new()
{
private readonly static T testInstance = new T();
public static int test() => testInstance.x;
}
This uses a new() condition, but an associated static, generic factory pattern for creating ITest (or TestClass or AbstractTestClass) instances may also be used.
However this may not be feasible if you can't have long-lived instances of the class.
In this situation you assume that T is a subclass of TestClass. Subclasses of TestClass will not have the static int x.
I want to create an extendable nested structure and it seems like I should be able to do this using generics, though I may not be using them "properly".
I want to be able to create child classes from GroupType and/or OptionType. The problem is that I can't perform the new operation on the generic types even though I specified they could only be of a certain base type.
Is there any way to do what I'm trying to do?
public class AllInfo<GroupType, OptionType>
where GroupType: GroupBase<OptionType>
where OptionType: OptionBase
{
public List<string> Names { set; get; }
public List<GroupType> Groups { set; get; }
public AllInfo()
{
DataSet ds = DatabaseRetreival();
this.Groups.add(new GroupType(ds["Name"], ds["Type"]));
}
}
public class GroupBase<OptionType>
where OptionType: OptionBase
{
public string Name { set; get; }
public string Type { set; get; }
public List<OptionType> Options { set; get; }
public GroupBase(string name, string type)
{
this.Name = name;
this.Type = type;
DataSet ds = DatabaseRetreival(this.Type);
this.Options.Add(new OptionType(ds["Name"]));
}
}
public class OptionBase
{
public string Name { set; get; }
public OptionBase(string name)
{
this.Name = name;
}
}
You have to specify the classes must have a default constructor.
where GroupType: GroupBase<OptionType>, new()
View this article and jump down to the section titled Generic Constraints.
You can't specify which constructors a generic class should have. The constructors are not inherited, so even if the base class that you specified has that constructor, a class that derives from it doesn't have to have that constructor.
The only constructor that you can require is the parameterless constructor:
where GroupType: GroupBase<OptionType>, new()
As that only let's you use the parameterless constructor, you would also use a virtual method for putting the data in the object, for example:
GroupType group = new GroupType();
group.Init(ds["Name"], ds["Type"]);
this.Groups.add(group);
The compiler cannot allow that, because it cannot guarantee that the OptionType has a constructor with the right signature. But you can pass a factory function instead of invoking the constructor directly:
public class Foo<T>
{
private List<T> myObjects;
public Foo(Func<string, T> factory))
{
myObjects = new List<T>();
foreach (string s in GetDataStrings())
myObjects.Add(factory(s));
}
}
So if you have a Bar class with a constructor taking a string, you do this:
Func<string,Bar> barFactory = x => new Bar(x);
var foo = new Foo<Bar>(barFactory);
The problem you have is foundationally based in very high amounts of class coupling that you are trying to mitigate with inheritance/generics. I suggest you re-examine why you feel this is necessary. This quest will eventually lead you to interfaces, service-based programming, and IoCs like Ninject or Castle Windsor.
However, if you want a quick fix that further increases code complexity (because you don't have non-complex options here aside from changing your coding philosophy), use an abstract/virtual method, maybe call it Bind(), instead of constructors.
[bolded for tl;dr]