Steve Jackson

Hello all.

The below code won't work, but it shows what I am trying to do; Basically, I want to create a Generic class (GClass), create a class that uses it (SomeClass), then instanciate the second class from a third class, passing an instance of the Generic class whose type has been defined.

I don't want to make the second class (SomeClass) generic if I can avoid it, and I would wrather not have to use 'object' boxing and unboxing as a crutch. Can anybody help me fix this code

Code Snippet

class GClass<T>

{

}

class SomeClass

{

private GClass<object> myGeneric;

internal GClass<object> MyGeneric

{

set

{

myGeneric = value;

}

}

}

class SomeOtherClass

{

private GClass<int> myGeneric = new GClass<int>();

private SomeClass myClass = new SomeClass();

SomeOtherClass()

{

// This gives a compile error, cannot implictely convert

// I don't know the syntax for making the conversion.

myClass.MyGeneric = myGeneric;

}

}

Thanks,

SteveJ




Re: Visual C# General Instanciating generic without giving type;

Steve Jackson

OK,

after some reading, I've come up with the code below. It is very close to what I need with one small exception; If you look at the class below, that I called Generic, you will see my comments. I would like to restric T to a class that implements ITest. If I add ITest, though, I have to provide a data type.

Code Snippet

class Program

{

static void Main(string[] args)

{

GTest<int> myTest = new GTest<int>();

Generic<GTest<int>> myGeneric = new Generic<GTest<int>>();

myGeneric.TheInterface = myTest;

}

}

interface ITest<T>

{

}

class GTest<T> : ITest<T>

{

}

class Generic<T>

where T: class // I would like to have this say "where T: class, ITest"

{

T myInterface;

internal T TheInterface

{

set

{

myInterface = value;

}

}

}






Re: Visual C# General Instanciating generic without giving type;

Steve Py

The thing about Generics to always keep in mind is that they are compile time optimizations, not runtime elements. When you declare a generic to accept a type, it essentially tells the compiler to create a object from the template of the generic that is coded to work with that type. This is why they're not suited for converting from one type to another.

Your second attempt is a bit closer. Really, all you need to do is use "where T: ITest". The "gotcha" is that *only* a class can ultimately extend an interface so you don't need to specify the interface & the class keyword. Smile






Re: Visual C# General Instanciating generic without giving type;

Steve Jackson

While I certainly appreciate the response, Steve, that solution does not compile as well. The compiler is looking for a type after Itest, ex. "where T: ITest<int>". This, however, leads me back to my original problem. I can simply use "where T: class" - which works, but then I can't guarantee that the class that was passed will implement ITest.

Thanks






Re: Visual C# General Instanciating generic without giving type;

Thomas Danecker

I think you're looking for something like this:

Code Snippet

class Generic<T, U>

where T : ITest<U>

{

T myInterface;

internal T TheInterface

{

set

{

myInterface = value;

}

}

}






Re: Visual C# General Instanciating generic without giving type;

nikov

>The "gotcha" is that *only* a class can ultimately extend an interface so you don't need to specify the interface & the class keyword.

Hi Steve.
I do not think so.

Code Snippet

interface ITest { }

struct Test : ITest { }

class Program
{
static void Main()
{
Foo(new Test());
}

static void Foo<T>(T x) where T : struct, ITest
{

}
}






Re: Visual C# General Instanciating generic without giving type;

Steve Py

Fine nikov, go file a lawsuit if you want to dive into pedantics rather than contribute something useful. (Struct = for all intensive purposes a class on the Stack) Wondering if anyone would bother restricting a generic to classes and exclude structs wasn't at the top of my mind...

However back to the original question: Sorry Steve I had missed that you had declared the Interface as a generic itself. Just curious but does your interface need to expose methods, if not the interface should serve the purpose without being a generic.






Re: Visual C# General Instanciating generic without giving type;

Steve Jackson

Thank you for the help, Thomas. This is certainly an option, and may be the one that I have to eventually use. Still, though, I was hoping not to have to use this method. Since ITest itself is a generic, it already has its type defined when Generic is instantiated. Adding the U is duplicate information and can lead to errors, ex. "Generic<GTest<int>,string>".

Thanks






Re: Visual C# General Instanciating generic without giving type;

Steve Jackson

Steve,

Well said. Unfortunately, I do need to expose methods.

Thanks






Re: Visual C# General Instanciating generic without giving type;

Thomas Danecker

You could also do the following if it fits your needs (but I assume it doesn't):

Code Snippet

class Generic<T>

where T

{

ITest<T> myInterface;

internal ITest<T> TheInterface

{

set

{

myInterface = value;

}

}

}

In your error-case example, a compile-time error would be generated which is easy to recognice and correct.

By the way, it's quite important to distinguish between structs and classes: stucts are value types and so they have by-value semantics and classes are reference types and have by-ref semantics. That's a very huge difference. It's much more than just "Struct = for all intensive purposes a class on the Stack". There are quite more differences when it comes to inheritance and implementation of interfaces. Classes and structs are completely different constructs. That's one of the most important facts that you've to understand when you want to be successful at programming with the .net Framework.






Re: Visual C# General Instanciating generic without giving type;

Steve Jackson

OK Thomas, Steve;

Thanks again for your help. It looks as if I'm just going to have to cary over the Generic aspect all the way down (as per the last example) and clearly document this. I appreciate your point, Thomas, about it being a compile-time error.

As far as your comments go about Structures and Classes, I've been doing a lot of reading on the subject lately; For whatever reason it seems to be one of those concepts, like pointers, that a person just has to exposed to for a while to gain complete clarity. In all of my reading, however, I haven't seen any best practices for when to choose one over the other.

Thanks






Re: Visual C# General Instanciating generic without giving type;

Steve Py

Yes, structs have differences from classes, but as far as interfaces go with them vs. classes, the only significant difference I'm aware of is a reasonably small performance hit since the byval representation needs to be boxed. My beef is not with having something I say taken too literally and corrected, it's when someone (nikov) butts in to point out some trivial point without offering anything better to address the original issue. My comment about interfaces and classes reflects that :under general terms: if you restrict a generic to an interface, you wouldn't need to specify a class restriction as well. If excluding structs is a requirement from the OP then they can point that out themself.

I consider proper design a more important fact when you want to be successful at programming with any language. Most of the posts listed on this forum (not necessarily this post) stem from incomplete thought on the problem domain. Initially I did miss the fact that the interface declaration was a Generic, & that the error he was getting was that he tried to refer to the interface without it's generic Type. According to the OP the generic interface is a valid design requirement.

Back to the original problem,

Depending on the way you're looking to use the Type within the Generic class itself, another option you might consider is to try something like:

// For internal use to expose functionality needed within Generic<>
interface ITestable
{ }

// For external use where you want to incorporate type specific functionality (Specifically outside Generic<>)
interface ITest<T> : ITestable
{ }

class Generic<T> where T: class, ITestable
{ }

Unfortunately this doesn't restrict someone from implementing ITestable in another "class" and using it, but if you want "any" ITest< > to work within a Generic class, you'll need to abstract the generic interface into something that exposes a commonly compatible signature. If you want to use an ITest< > inside Generic specifically, because generics are compile time, the declaration of Generic<> needs to specify the generic type of ITest to use.










Re: Visual C# General Instanciating generic without giving type;

Thomas Danecker

I rarely have the need of defining a struct. Just use them if you really need by-value semantics. Structs may be helpful for some additional low-level data types (System.Decimal is a good example). Also if some classes are used damn frequently (e.g. in computer games, etc.), you may consider to use a struct because you can reduce cache-misses and memory usage (if used correctly). I recommend that everyone should start by using a class and only if you really discover the need of a struct, use a struct, but be very careful when you design a complex struct because there are manny performance pitfalls.