❔ 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 D 」13mo 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
reflectronic13mo ago
which code is it saying will be unreached
「 V E L D 」
「 V E L D 」13mo ago
every single case of the switch they are all told as unreachable
reflectronic
reflectronic13mo ago
what is the exact error it tells you
「 V E L D 」
「 V E L D 」13mo 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
reflectronic13mo 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 D 」13mo ago
Oh sure.. Oh yeah I see And can the type argument be omitted when T is putted before ? Or not ?
reflectronic
reflectronic13mo ago
what do you mean by "if it's specified before"
「 V E L D 」
「 V E L D 」13mo ago
Like uh
reflectronic
reflectronic13mo 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 D 」13mo ago
GetAsset<AudioClip>("AnAudioClip")
// equals
GetAsset(AudioClip, "AnAudioClip")
GetAsset<AudioClip>("AnAudioClip")
// equals
GetAsset(AudioClip, "AnAudioClip")
reflectronic
reflectronic13mo ago
no, because those are completely different things
「 V E L D 」
「 V E L D 」13mo ago
Ahhh
reflectronic
reflectronic13mo ago
T type means "give me a T"
「 V E L D 」
「 V E L D 」13mo ago
Yeah an instance...
reflectronic
reflectronic13mo ago
"give me an AudioClip"
「 V E L D 」
「 V E L D 」13mo ago
that's not what I want...
reflectronic
reflectronic13mo ago
i think you will have to give up the switch here
「 V E L D 」
「 V E L D 」13mo ago
Oh wait if I do new T() ?
reflectronic
reflectronic13mo 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 D 」13mo 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
reflectronic13mo ago
no, it would not
「 V E L D 」
「 V E L D 」13mo ago
it's not making any error in my IDE oh...
reflectronic
reflectronic13mo ago
it will make an error when you do GetAsset<Material> or GetAsset<AudioClip>
「 V E L D 」
「 V E L D 」13mo ago
Ah... That's annoying...
Moods
Moods13mo ago
Curious, why’s that?
reflectronic
reflectronic13mo 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 D 」13mo ago
Ah... I see... Well then I'll do your thing And can't I make a switch(true) { case true when typeof... } ?
reflectronic
reflectronic13mo ago
i suppose you could
「 V E L D 」
「 V E L D 」13mo ago
Okay alright
「 V E L D 」
「 V E L D 」13mo ago
Thanks, it does not look to bad
「 V E L D 」
「 V E L D 」13mo ago
I'll obviously add a check if result is null Ah It will an exception before lol Thanks for help ThumbsUp
JenyaRostov
JenyaRostov13mo 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
Accord13mo 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.