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