Okay, my image is getting clearer. Seems like every time I’ve attempted to respond to this post I’ve been strapped for time so, I apologize for my omissions.
So I said I would explain why that code snippet wouldn’t compile and then I didn’t. Oops.
Think of the bit inside the angle bracket this way: it is a hint to the compiler. Like I said before, one of the purposes of generic programming is to provide the compiler more information so that it can make extra optimizations or handle type safety for us. When we write a generic class or method, we use a variable for the type because we want the code to be suitable to more than one type. However, when we use the generic class or method, we need to decide on a specific type and give a hint to the compiler inside of the angle brackets. This is the crux of your problem: it is the compiler that needs the information inside the angle brackets but you are using .GetType() which returns an instance of a Type object at runtime.
By the time GetType() is called, it’s far too late to be any use to the compiler. So you’re left with a catch-22. You need the type to help the compiler out but you need the compiled code to get the type.
Let’s go back to why we need to know the type in the first place: I already mentioned these two: optimization and type safety. Now I’ll add one more: the author of the generic code might want to know certain things about the type. Well, since we have the source for the generic method you are implementing we can analyze it.
Let’s talk about GetCopyOf(T other) first.
First of all, I see they author has put a restriction on the types of objects that can be passed in:
public static T GetCopyOf<T>(this Component comp, T other) where T : Component
where T : Component says that this method will only accept objects of type Component. Anything else will cause a compile time error.
Next, the Author immediately uses .GetType() to determine the runtime type of the object coming in.
Type type = comp.GetType();
if (type != other.GetType()) return null;
We already know that it has to be of type Component, but GetType() will tell us which specific implementation of Component, that is the type of class that inherited from Component, we have.
At this point, the author doesn’t seem to care about what type is passed in. They treat it in a very generic way, simply asking for the first instance’s properties and then setting the properties of the second.
I would say we are okay to use any type so long it is a Component. It’s perfectly okay to call GetCopyOf like this:
component.GetCopyOf<Component>(otherComponent);
And it doesn’t matter if component and otherComponent are actually Joint Components, so long as they have the same type.
A point of interest:
since the signature of this method looks like: GetCopyOf(T otherComponent), the compiler can get its hint without the angle brackets. That’s because it will know what type otherComponent is at compile time and it can then deduce that T = T. So we can make the call even simpler:
component.GetCopyOf(otherComponent);
Now let’s deal with the second extension method which is the one you are actually trying to use:
public static T AddComponent<T>(this GameObject go, T toAdd) where T : Component
{
return go.AddComponent<T>().GetCopyOf(toAdd) as T;
}
In this code, the author makes use of the generic method AddComponent(), so now things get interesting. In order to use this method, we need to know the very specific type of component we want to add because AddComponent() does the instantiation of that component for us. Unfortunately, in your situation, we simply can’t know the type at compile time unless we use type checking for each possible type. Something like:
for (int i = 0; i < components.Count; i++)
{
foreach (Component component in components[i])
{
if (component is Joint)
{
destinationBones[i].gameObject.AddComponent<Joint>(component);
} else if (component is FixedJoint)
destinationBones[i].gameObject.AddComponent<Joint>(component);
//etc...
}
}
However, I don’t really like to dirty my code up with all those if and else ifs. It makes our code ugly and it also creates a dependency for this code on all the possible types of Components we want to handle. This defeats the purpose of generic programming.
So, here’s an alternative. Let’s change the authors implementation of AddComponent() to make it look more like the non-generic flavor of AddComponent().
public static Component AddComponent(this GameObject go, Component toAdd)
{
return go.AddComponent(toAdd.GetType().Name).GetCopyOf(toAdd);
}
Also, I’m looking more carefully at the documentation for AddComponent. Wow is it bad! I can’t tell what the return type is and I think there actually might be an overload for this method which takes the strongly qualified type Type instead of a string for the class name, so let’s try this so that we don’t need to access the .Name.
public static Component AddComponent(this GameObject go, Component toAdd)
{
return go.AddComponent(toAdd.GetType()).GetCopyOf(toAdd);
}
Now we can use our new extension method like so:
for (int i = 0; i < components.Count; i++)
{
foreach (Component component in components[i])
{
destinationBones[i].gameObject.AddComponent(component);
}
}