generic variable declaration - c#

I am not sure if this can be accomplished at all but here is my question.
Using C#, is it possible to declare a generic or non-typed variable but later in my code specify what that variable should be?
object genericObject;
if (!testFlag)
{
genericObject = new SpecificObject1();
}
if (testFlag)
{
genericObject = new SpecificObject2();
}
genericObject.FirstName = "Samuel";
genericObject.LastName = "Jackson";
I am hoping that after the "if logic" I can now call the similar methods each "specific" object had in common.
So is it possible to create some form of generic object in the beginning of my code and instantiate the specific object I want to use later?
Maybe there is a design pattern or refactoring effort that needs to be considered here as well.

If both SpecificObject1 and SpecificObject2 share similar properties, you could add an interface for them. You could then declare genericObject as the interface type and assign the concrete type later:
public interface SomeInterface
{
string FirstName { get; set; }
string LastName { get; set; }
}
public class SpecificObject1 : SomeInterface
{
// Implementation Details
}
public class SpecificObject2 : SomeInterface
{
// Other Implementation Details
}
You would then be able to use them in the following manner:
SomeInterface genericObject;
genericObject = testFlag ? new SpecificObject2() : new SpecificObject1();

I'd recommend you define a custom interface that encapsulates all the members you need to use, and implement it on both of your concrete types::
interface IMyInteface
{
string FirstName { get; set; }
string LastName { get; set; }
}
class SpecificObject1 : IMyInterface { ... }
class SpecificObject2 : IMyInterface { ... }
And then declare your variable to be an instance of that interface:
IMyInterface genericObject;
if (!testFlag)
{
genericObject = new SpecificObject1();
}
if (testFlag)
{
genericObject = new SpecificObject2();
}
genericObject.FirstName = "Samuel";
genericObject.LastName = "Jackson";
But if that's not an option, you could use dynamic, which will force any members to be evaluated at run time:
dynamic genericObject;
if (!testFlag)
{
genericObject = new SpecificObject1();
}
if (testFlag)
{
genericObject = new SpecificObject2();
}
genericObject.FirstName = "Samuel";
genericObject.LastName = "Jackson";

You need to move all of the common members to a common base class or interface, then declare the variable as that type.

If your types, you are going to assign later, are completely unrelated to each other and mainly have different set of methods to execute, dynamic could be your choice of preference in this case.
In other cases, use standard OOP techniques, like inheritance and polymorphism to achieve what you are talking about.

Related

Generic class with generic constructor? [duplicate]

This question already has an answer here:
Generic Type in constructor
(1 answer)
Closed 2 years ago.
I have a generic class. The constructor needs to accept an argument that is another instance of the same class. The problem is that the other instance can have a different generics type.
Looks like C# allows me to have a method with it's own generics type, but this doesn't appear allowed for the constructor.
public class MyClass<T>
{
public MyClass<T2>(MyClass<T2> parent = null)
{
}
// ... Additional stuff
}
The code above tells me T2 is undefined. It doesn't accept it as a method type.
One approach would be to add a second generic type to my class. But this is awkward and, in many cases, the argument will be null and there is not type.
Does anyone see a simple way around this?
Generic constructors aren't allowed. However, you can use a generic factory method instead.
public class MyClass<T>
{
public int Id { get; private set; }
public int? ParentId { get; private set; }
public static MyClass<T> Create(int id)
{
return Create<object>(id, null);
}
public static MyClass<T> Create<T2>(int id, MyClass<T2> parent = null)
{
var current = new MyClass<T>();
current.Id = id;
current.ParentId = parent?.Id;
return current;
}
private MyClass()
{
}
// ... Additional stuff
}
Sample use:
var intClass = MyClass<int>.Create(55);
var charClass = MyClass<char>.Create(234, intClass);
// charClass.ParentId is 55
This is only possible if you do not need to access any generic members of parent outside the factory method. If you do, you'd be better off abstracting it through a non-generic interface or base class.
You are correct. Generic constructors aren't supported.
You could probably try the following:
Create a lower level common interface
public interface IMyClass {
//...some common stuff
IMyClass Parent { get; set; }
}
And use that as the common link between the types
public class MyClass<T> : IMyClass {
public MyClass(IMyClass parent = null) {
Parent = parent;
}
public IMyClass Parent { get; set; }
// ... Additional stuff
}

Interface generic parent child object initialization

I have a interface with constraint as a Base class
abstract class BaseElement { };
interface IOperation <T>where T:BaseElement
{
void Add (T field1);
}
Created a child object for the Base class
class StudentDTO : BaseElement
{
public int Id { get; set; }
};
class SubjectDTO : BaseElement
{
public string Name { get; set; }
};
Implemented 2 classes with IOperation interface
class Student : IOperation<StudentDTO>
{
public void Add(StudentDTO field1)
{
Console.WriteLine("Child A" + field1.Id);
}
}
class Subject : IOperation<SubjectDTO>
{
public void Add(SubjectDTO field1)
{
Console.WriteLine("Child B" + field1.Name);
}
}
Implemented a factory pattern to return the DTO objects.
static class BLFactory
{
public static IOperation<BaseElement> CreateObject(BaseElement baseObject)
{
if (baseObject.GetType().Name == "SubjectDTO")
{
return new StudentDTO() as IOperation<BaseElement>;
}
else
{
var temp = new SubjectDTO() as IOperation<BaseElement>;
return temp;
////************ temp object returns null *************
}
}
}
Now, when I use the BLFactory to create the DTO objects, I am getting it as NULL. Not sure how to fix the problem.
Any advice how to fix this or what is the right way of implementing.
Well, first off StudentDTO doesn't implement IOperation at all; Student does, but StudentDTO doesn't.
And even if you did use Student that wouldn't work either. Student implements IOperation<StudentDTO> not IOperation<BaseElement>.
Just because StudentDTO can be implicitly converted to BaseElement does not mean that IOperation<StudentDTO> can be implicitly converted to IOperation<BaseElement>. IOperation would need to be covariant for that to be the case, and it's not.
If you wanted, you could make IOperation contravariant, given that T is only used as input, but that would then enable you to implicitly convert an IOperation<BaseElement> to an IOperation<StudentDTO>, not the reverse.
According to documentation of as operator:
The as operator is like a cast operation. However, if the conversion isn't possible, as returns null instead of raising an exception.
As StudentDTO is not inherited from IOperation<...> and SubjectDTO is not inherited from IOperation<...> you will get null in temp variable as result of as operatior.
Because SubjectDTO is NOT an IOperation<BaseElement>. It is a BaseElement.
Neither is a Subject - it is an IOperation<SubjectDTO> which does NOT inherit from IOperation<BaseElement>.
It seems like your BLFactory is basically returning the proper "repository" for each type, which may be better done declaratively using a DI framework like Ninject or Unity.
However, if you want to hard-code it, you could make BLFactory generic:
static class BLFactory<U> where U:BaseElement
{
public static IOperation<U> CreateObject()
{
if (typeof(U).Name == "SubjectDTO")
{
return new Student() as IOperation<U>;
}
else
{
return new Subject() as IOperation<U>;
}
}
}

Extending using C# generics?

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]

Generics: How to check the exact type of T, without object for T

How can i check/evaluate the exact type of T without an object for T. I know my question maybe confusing but consider this...
public abstract class Business
{
public abstract string GetBusinessName();
}
public class Casino : Business
{
public override string GetBusinessName()
{
return "Casino Corp";
}
}
public class DrugStore : Business
{
public override string GetBusinessName()
{
return "DrugStore business";
}
}
public class BusinessManager<T> where T : Business
{
private Casino _casino;
private DrugStore _drugStore;
public string ShowBusinessName()
{
string businessName;
if (T == Casino) // Error: How can I check the type?
{
_casino = new Casino();
businessName = _casino.GetBusinessName();
}
else if (T == DrugStore) // Error: How can I check the type?
{
_drugStore = new DrugStore();
businessName = _drugStore.GetBusinessName();
}
return businessName;
}
}
I just want to have something like this on the client.
protected void Page_Load(object sender, EventArgs e)
{
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
businessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
}
Notice that I actually didnt create the actual object for Casino and Drugstore when I call the BusinessManager, I just pass it as generic type constraint of the class. I just need to know exactly what Type i am passing BusinessManager to know what exactly the Type to instantiate. Thanks...
PS: I don't want to create separate specific BusinessManager for Casino and Drugstore..
You can also comment about the design.. thanks..
ADDITIONAL: and what if class Casino and DrugStore is an ABSTRACT CLASS =)
You can write
if(typeof(T) == typeof(Casino))
but really this type of logic is a code smell.
Here's one way around this:
public class BusinessManager<T> where T : Business, new() {
private readonly T business;
public BusinessManager() {
business = new T();
}
}
but personally I'd prefer
public class BusinessManager<T> where T : Business {
private readonly T business;
public BusinessManager(T business) {
this.business = business;
}
public string GetBusinessName() {
return this.business.GetBusinessName();
}
}
You should do
public class BusinessManager<T> where T : Business, new()
...
T _business = new T();
string businessName = _business.GetBusinessName();
return businessName;
I don't know about C# syntax, but is it not possible to do:
public class BusinessManager<T> where T : Business, new()
{
private T _business;
public string ShowBusinessName()
{
string businessName;
_business = new T();
return _business.GetBusinessName();
}
}
Since other guys have already shown various answers to your first question, I would like to address the second one: design.
1. Role of BusinessManager
Actual role of the BusinessManager class in your example is not too clear. Since this class is generic, and it shouldn't be concerned with the actual type of T, then it does nothing more than add another unnecessary layer between the Business class and the rest of the program.
In other words, you can simply use:
Business casino = new Casino();
Response.Write(casino.GetBusinessName());
Business drugStore = new DrugStore();
Response.Write(drugStore.GetBusinessName());
Wrapping this in another generic class doesn't help you a lot. On the other hand, if you want to have some common functionality for all these classes, you can either add it directly to your abstract class, or extract an interface and create extension methods for that interface.
2. Using properties for getters
Second thing, using a property is more appropriate when you have a simple getter method. In other words, you should replace GetBusinessName() method with a Name property (I also omitted the "Business" from the name because it is not necessary:
public interface IBusiness
{
string Name { get; }
}
public abstract class Business : IBusiness
{
public abstract string Name { get; }
}
public class Casino : Business
{
public override string Name
{
get { return "Casino Corp"; }
}
}
public class DrugStore : Business
{
public override string Name
{
get { return "DrugStore business"; }
}
}
And then you can use it like this:
IBusiness casino = new Casino();
Response.Write(casino.Name);
IBusiness drugStore = new DrugStore();
Response.Write(drugStore.Name);
Also, you can see that I have introduced a IBusiness interface. The reason for doing so is to allow you to implement this interface in more diverse ways. Right now, you will try to derive all your classes from the abstract Business class, and try to extract as much of the common functionality in the abstract class (that's the purpose of the class).
But extracting lots of common functionality comes with a cost: there is always a possibility that you will come up with a need to create a class which isn't derived from Business. If you are accessing all these methods through the IBusiness interface, then other parts of your program won't care if that implementation is derived from Business or not.
Since GetBusinessName really applies to the type and not instances of the type, you might consider using DescriptionAttribute (or your own BusinessNameAttribute) instead of an overridden property and have your BusinessManager get the business name from the attribute.
[Description("Casino Corp")]
public class Casino : Business
{
}
Now you no longer need to instantiate the business just to gets its name. To get the description, you use:
public string ShowBusinessName()
{
var attribute = Attribute.GetCustomAttribute(typeof(T), typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute == null)
return "Unknown business";
return attribute.Description;
}
You can do something like this:
if (typeof(T) == typeof(SomeType))
{
// Same
}
define a BusinessManager class as bellow:
public class BusinessManager<T> where T : Business
{
Business biz;
public BusinessManager()
{
biz = new T();
}
public string ShowBusinessName()
{
return biz.GetBusinessName();
}
}
and use it as bellow:
var businessManager = new BusinessManager<Casino>();
Response.Write(businessManager.ShowBusinessName());
var anotherBusinessManager = new BusinessManager<DrugStore>();
Response.Write(businessManager.ShowBusinessName());
The way you using you will lost encapsulation
In VB.net you can use the GetType pseudo-function on a generic type parameter to get a reflection Type object. I would guess C# should have an equivalent. If for whatever reason you can't use something like that, you could create an array of 0 elements of the desired type, and then check the type of that array. That would probably be cheaper than instantiating an element of the unknown type.

Can you use the C# new keyword to expand properties on an interface?

I understand how the "new" keyword can hide methods in a derived class. However, what implications does it have for classes that implement interfaces that use the keyword?
Consider this example, where I decide to expand an interface by making its properties read/write.
public interface IReadOnly {
string Id {
get;
}
}
public interface ICanReadAndWrite : IReadOnly {
new string Id {
get;
set;
}
}
Then you are able to do things like this:
public IReadOnly SomeMethod() {
// return an instance of ICanReadAndWrite
}
Is this bad design? Will it cause issues for my classes that implement ICanReadAndWrite?
Edit: Here is a contrived example of why I might want to do something like this:
Say I have a factory class that returns an IShoppingCartItemReadWrite. I can then have a service layer that manipulates prices on it, changes stuff, etc. Then, I can pass these objects as IShoppingCartItemReadOnly to some kind of presentation layer that won't change them. (Yes, I know it technically can change them-- this is a design question, not security, etc.)
It's not a particularly bad idea. You should be aware that the implementor can (if it implicitly implements the interface, then a single read/write property could satisfy both interfaces) provide two distinct implementations:
class Test : ICanReadAndWrite {
public string Id {
get { return "100"; }
set { }
}
string IReadOnly.Id {
get { return "10"; }
}
}
Test t = new Test();
Console.WriteLine(t.Id); // prints 100
Console.WriteLine(((IReadOnly)t).Id); // prints 10
By the way, in general, the new inheritance modifier does nothing except to tell the compiler to shut up and don't throw out a "you're hiding that member" warning. Omitting it will have no effect in the compiled code.
You should not implement the ICanReadWrite based on IReadOnly, but instead make them separate.
ie. like this:
public interface IReadOnly
{
string Id
{
get;
}
}
public interface ICanReadAndWrite
{
string Id
{
get;
set;
}
}
Here's a class using them:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
}
Note that the same property in the class can support both interfaces.
Note that as per the comment, the only way to get a robust solution would be to also have a wrapper object.
In other words, this is not good:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
public IReadOnly AsReadOnly()
{
return this;
}
}
as the caller can just do this:
ICanReadWrite rw = obj.AsReadOnly() as ICanReadWrite;
rw.Id = "123";
To get a robust solution, you need a wrapper object, like this:
public class SomeObject : IReadOnly, ICanReadWrite
{
public string Id
{
get;
set;
}
public IReadOnly AsReadOnly()
{
return new ReadOnly(this);
}
}
public class ReadOnly : IReadOnly
{
private IReadOnly _WrappedObject;
public ReadOnly(IReadOnly wrappedObject)
{
_WrappedObject = wrappedObject;
}
public string Id
{
get { return _WrappedObject.Id; }
}
}
This will work, and be robust, right up until the point where the caller uses reflection.
This is perfectly legal and the implications for your class that implements the ICanReadAndWrite interface would simply be that when it is treated as an IReadOnly it can only read, but when treated as ICanReadAndWrite it would be able to do both.
I'm not sure if that compiles or not, but is not an advisable pattern to follow. With the ability to do explicit interface implementation, you could theoretically provide two entirely different implementations for the IReadOnly and ICanReadAndWrite versiond of the Id property. Consider altering the ICanReadAndWrite interface by adding a setter method for the property rather than replacing the property.
You can do it but I am not sure what you hope to accomplish by doing it.
public IReadOnly SomeMethod() {
// return an instance of ICanReadAndWrite
}
This method will return a reference to an IReadOnly which means that it doesn't matter that you have returned an ICanReadAndWrite. Wouldn't this approach be better?
public interface IReadOnly
{
String GetId();
}
public interface ICanReadAndWrite : IReadOnly
{
String SetId();
}

Categories