You are really asking (at least) two different questions here: how to have a single method handle different types for a given parameter, and how to have a single variable store different types.
The former is in fact often addressed by adding overloads; e.g. declare both test(string param1)
and test(int param1)
. In some cases, a single generic method would suffice. It depends on how the parameter will actually be used in the method.
As for the latter question, that's a bit more complicated and would depend heavily on the exact reasoning behind wanting a single variable to be able to store different types. In some cases, again, the variable might be declared in a generic context (type or method).
In other cases, one might use the dynamic
type, which is a mechanism that defers compilation of the code that uses the dynamic
value until runtime when the type is actually known (for obvious reasons, this can make the code a lot slower…it's optimized as well as can be, but it's still adding a lot of overhead).
Bottom line, the short answer to your question:
does c# have something similar that doesn't require overloading?
…lacking any additional information for why you think you need this feature, is that while overloading would in fact be the first choice, it is possible that generic types or methods might address your need.
The above should answer the question you posted here, such as it is. The question is too vague to provide anything more specific. If you need more specific information, you should post a new question that takes the feedback you've received here into account but elaborates on the specific scenario you are trying to address.
Addendum:
Based on your edited question, it seems you want to do something like this:
public float getPlaybackLength(AudioSource[] tracks, FlexibleEnumType trackIndex) {
return tracks[trackIndex].clip.length;
}
and pass in either a Musics
value or Sfx
value.
Given that, I'd recommend the following alternative:
public float getPlaybackLength(AudioSource track) {
return track.clip.length;
}
where you'd call it like this:
Musics trackId = Musics.music1;
float length = getPlaybackLength(musics[(int)trackId]);
Alternatively:
public float getPlaybackLength(AudioSource[] tracks, int trackIndex) {
return tracks[trackIndex].clip.length;
}
called as
Musics trackId = Musics.music1;
float length = getPlaybackLength(musics, (int)trackId);
Note that even if you wrote a method that took either enum
type for that parameter (and you could, using generics), you'd still need to cast the enum
value to an int
for the purpose of indexing the array. So you might as well cast before passing the value instead, for simplicity.
As I mentioned, you could write a generic method that can accept either enum
type, but you wouldn't be able to restrict it to just those two enum
types, and the casting in the method body from the enum
value to an int
is a bit awkward, because you won't be able to cast directly from the type parameter type. It would involve casting to object
first, which results in a boxing and unboxing conversion just to accomplish the cast.
If you really want a 100% type-safe approach that involves passing the enum
value rather than casting to int
for the call, you should just go ahead and write a couple of overloads for the purpose.
One final thought: maybe your AudioSource
type could itself provide a convenience property that returns the clip.length
property value. If that's not your own type, you could write a user-defined type that wraps an object of that type and provides the convenience property itself. That way, rather than having to keep looking the object up in an array, you can just get the value directly from an object you already have.
Which, by the way, you could of course do from the AudioSource
object too, albeit with the property path clip.length
…frankly, that doesn't really seem all that bad to me. After all, a convenience property might be called something like ClipLength
anyway, which is basically the same amount of typing. Maybe you have other scenarios in mind, but the convenience method you used as an example doesn't really seem to add that much convenience anyway. :)