C
C#3y ago
V E L D

❔ How to make a method returning type T but only taking subclasses of a certain class ?

I'd like to make a function that takes the type T as an "argument" (T MyMethod<T>()), but the type T must be equal to Type Z or subclass of Type Z, how do I do that ? I'd like it search through defined dictionaries that are all typed as subclasses of Type Z.
34 Replies
V E L D
V E L DOP3y ago
I don't know if it's clear but uh... Basically this was the code I was planning to do, however it tells that some code will never be reached:
internal T GetAsset<T>(T type, string name) where T : UnityEngine.Object
{
UnityEngine.Object result;
switch(type)
{
case AudioClip a:
result = CachedAudioClips[name];
break;
case GameObject go:
result = CachedPrefabs[name];
break;
case Material mat:
result = CachedMaterials[name];
break;
case Mesh mesh:
result = CachedMeshes[name];
break;
case Sprite sprite:
result = CachedSprites[name];
break;
case Texture2D tex:
result = CachedTextures[name];
break;
default:
throw new ArgumentException("The type of T is not recognized as an UnityEngine.Object class or subclass, or it is not supported.");
}
return result as T;
}
internal T GetAsset<T>(T type, string name) where T : UnityEngine.Object
{
UnityEngine.Object result;
switch(type)
{
case AudioClip a:
result = CachedAudioClips[name];
break;
case GameObject go:
result = CachedPrefabs[name];
break;
case Material mat:
result = CachedMaterials[name];
break;
case Mesh mesh:
result = CachedMeshes[name];
break;
case Sprite sprite:
result = CachedSprites[name];
break;
case Texture2D tex:
result = CachedTextures[name];
break;
default:
throw new ArgumentException("The type of T is not recognized as an UnityEngine.Object class or subclass, or it is not supported.");
}
return result as T;
}
reflectronic
reflectronic3y ago
which code is it saying will be unreached
V E L D
V E L DOP3y ago
every single case of the switch they are all told as unreachable
reflectronic
reflectronic3y ago
what is the exact error it tells you
V E L D
V E L DOP3y ago
Okay I changed a line and it deleted the error... I don't know what happened but it was telling word for word "this code is unreachable" Although I need to know, can be the argument T type be omitted if it is specified before ? what I did before is that I deleted the T type argument and my switch was switch(default(T)) and there the code was unreachable
reflectronic
reflectronic3y ago
yes, that will not work null will not match any of them it will always go to default because null is not AudioClip or GameObject or Material
V E L D
V E L DOP3y ago
Oh sure.. Oh yeah I see And can the type argument be omitted when T is putted before ? Or not ?
reflectronic
reflectronic3y ago
what do you mean by "if it's specified before"
V E L D
V E L DOP3y ago
Like uh
reflectronic
reflectronic3y ago
GetAsset<T>(m, x) the <T> can be omitted if m has the type T e.g.
AudioClip a = ...
GetAsset(a, "abc");
AudioClip a = ...
GetAsset(a, "abc");
there is no other circumstance in which the <T> can be omitted
V E L D
V E L DOP3y ago
GetAsset<AudioClip>("AnAudioClip")
// equals
GetAsset(AudioClip, "AnAudioClip")
GetAsset<AudioClip>("AnAudioClip")
// equals
GetAsset(AudioClip, "AnAudioClip")
reflectronic
reflectronic3y ago
no, because those are completely different things
V E L D
V E L DOP3y ago
Ahhh
reflectronic
reflectronic3y ago
T type means "give me a T"
V E L D
V E L DOP3y ago
Yeah an instance...
reflectronic
reflectronic3y ago
"give me an AudioClip"
V E L D
V E L DOP3y ago
that's not what I want...
reflectronic
reflectronic3y ago
i think you will have to give up the switch here
V E L D
V E L DOP3y ago
Oh wait if I do new T() ?
reflectronic
reflectronic3y ago
if (typeof(T) == typeof(AudioClip)) return CachedAudioClips[name];
if (typeof(T) == typeof(GameObject)) return CachedPrefabs[name];
// ...
throw new ArgumentException(...);
if (typeof(T) == typeof(AudioClip)) return CachedAudioClips[name];
if (typeof(T) == typeof(GameObject)) return CachedPrefabs[name];
// ...
throw new ArgumentException(...);
V E L D
V E L DOP3y ago
Ah I see Is it possible to give several contraints to where T : new() & where T : UnityEngine.Object sorta ? oh yeah my bad im dumb lol i just had to put a comma Would this work ?
internal T GetAsset<T>(string name) where T : UnityEngine.Object, new()
{
UnityEngine.Object result = new T() switch
{
AudioClip => CachedAudioClips[name],
GameObject => CachedPrefabs[name],
Material => CachedMaterials[name],
Mesh => CachedMeshes[name],
Sprite => CachedSprites[name],
Texture2D => CachedTextures[name],
_ => throw new ArgumentException("The type of T is not recognized as an UnityEngine.Object class or subclass, or it is not supported."),
};
return result as T;
}
internal T GetAsset<T>(string name) where T : UnityEngine.Object, new()
{
UnityEngine.Object result = new T() switch
{
AudioClip => CachedAudioClips[name],
GameObject => CachedPrefabs[name],
Material => CachedMaterials[name],
Mesh => CachedMeshes[name],
Sprite => CachedSprites[name],
Texture2D => CachedTextures[name],
_ => throw new ArgumentException("The type of T is not recognized as an UnityEngine.Object class or subclass, or it is not supported."),
};
return result as T;
}
reflectronic
reflectronic3y ago
no, it would not
V E L D
V E L DOP3y ago
it's not making any error in my IDE oh...
reflectronic
reflectronic3y ago
it will make an error when you do GetAsset<Material> or GetAsset<AudioClip>
V E L D
V E L DOP3y ago
Ah... That's annoying...
Moods
Moods3y ago
Curious, why’s that?
reflectronic
reflectronic3y ago
because they do not meet the new() constraint they do not have a public, parameterless constructor it's probably true for other ones too but i didn't check all of them
V E L D
V E L DOP3y ago
Ah... I see... Well then I'll do your thing And can't I make a switch(true) { case true when typeof... } ?
reflectronic
reflectronic3y ago
i suppose you could
V E L D
V E L DOP3y ago
Okay alright
V E L D
V E L DOP3y ago
Thanks, it does not look to bad
V E L D
V E L DOP3y ago
I'll obviously add a check if result is null Ah It will an exception before lol Thanks for help ThumbsUp
JenyaRostov
JenyaRostov3y ago
could go even further and maybe do something like
public T GetAsset<T>(string name) where T : UnityEngine.Object
{
var type = typeof(T);
if(!CachedAssets.ContainsKey(type))
throw(...);
return CachedAssets[type][name];
}
public T GetAsset<T>(string name) where T : UnityEngine.Object
{
var type = typeof(T);
if(!CachedAssets.ContainsKey(type))
throw(...);
return CachedAssets[type][name];
}
where CachedAssets is
Dictionary<Type,Dictionary<string,UnityEngine.Object>>
Dictionary<Type,Dictionary<string,UnityEngine.Object>>
This way if you have a new asset type you want to cache you just add a key-value pair to CachedAssets dictionary
Accord
Accord3y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.

Did you find this page helpful?