Hopefully someone can shed some light on this one. I have an interface with an optional parameter. We use Unity. If I try to change the optional parameter in the method implementation, it works directly, but the Unity object uses the interface's default - not the implemented method's default.
Setup:
public interface ITestOptional {
string HappyMethod(string input, bool amHappy = false);
}
public class TestingOptional : ITestOptional {
public string HappyMethod(string input, bool amHappy = true) {
if (amHappy) return input + " is Happy!";
return input + " is Not Happy!";
}
}
Add to Unity:
container.RegisterType<ITestOptional, TestingOptional>();
And Test:
//direct call
var testDirect = new TestingOptional();
string happyDirect = testDirect.HappyMethod("Cow", true); //expecting happy - get happy
string sadDirect = testDirect.HappyMethod("Cow", false); //expecting not happy - get not happy
string defaultDirect = testDirect.HappyMethod("Cow"); //expecting happy (default) get happy
//unity
var testUnity = ServiceLocator.Current.GetInstance<ITestOptional>();
string happyUnity = testUnity.HappyMethod("Cow", true); //expecting happy - get happy
string sadUnity = testUnity.HappyMethod("Cow", false); //expecting not happy - get not happy
string defaultUnity = testUnity.HappyMethod("Cow"); //expecting happy (default) but get NOT happy.
Any ideas why the Unity object uses false as the optional parameter when the implementation uses true?
ServiceLocator.Current.GetInstance<ITestOptional>(); returns compile type ITestOptional, so call to testUnity.HappyMethod("Cow"); will be converted by compiler to use default value as specified in interface.
Similarly new TestingOptional(); returns compile time TestingOptional and compiler will pick default from the class.
Possible solution (short of adjusting expectations/not using different defaults): you can resolve that type directly using Unity instead of resolving interfce (sometimes useful for tests):
var directViaContainer = container.Resolve<TestingOptional>();
Side note: re-defining default values in class implementing an interface is not a god practice - you'll get into this confusing code often.
This has nothing to do with Unity. This is how C# compiler works. Optional arguments are filled in by the compiler at compile time. In the first example you call the HappyMethod method on the concrete type and that optional attribute is marked with true, so the C# compiler will fill in true for you. In the second example however, the C# compiler has no idea of the existence of the implementation, so it will look at the definition of the interface. And guess what: that interface is marked with false.
You have to use the Resolve<T> method, from an IUnityContainer instance. For sample:
var testUnity = container.Resolve<ITestOptional>();
In your first example, your testDirect is an instance of type TestingOptional, for which you invoke its HappyMethod overload directly, using it's specified default parameter value of true.
In your second example, your testUnity is an instance of type ITestOptional and you invoke its HappyMethod that specifies a different default parameter value of false.
This is unrelated to how you created these instances. You would have observed the same if you had done:
ITestOptional x = new TestingOptional();
x.HappyMethod("Cow");
Related
I have two enums.
The first is PrimaryColor which can be "Red, Yellow, or Blue"
The second is TertiaryColor which can be "Red, Magenta, Purple, Violet, Blue, etc"
I want my custom inspector to show only a subset of possible values to choose for the second enum based on the value of the first enum. So if it was Blue, I would want the user to be able to choose from "purple, violet, teal, magenta, blue," but not red/orange/etc.
I found that there is an option in the custom inspector "checkEnabled" that sounds like it would be perfect for this:
https://docs.unity3d.com/ScriptReference/EditorGUILayout.EnumPopup.html
However I'm not able to get it to compile when attempting to use this field.
Could anyone give me an example on how to go about using the checkEnabled field of EnumPopUp to do this? I can get the enumPopup method to work just fine with the basic parameters passing it a string and enum, however when I attempt to pass it the custom function method it says that all of the parameters can't be converted into GUIlayoutoptions.
//The variation of the method I am attempting to run
public static Enum EnumPopup(GUIContent label, Enum selected, Func<Enum,bool> checkEnabled,
bool includeObsolete, params GUILayoutOption[] options);
MyColor myColor = (MyColor)target;
Func<TertiaryColorEnum, bool> showEnumValue = ShowEnumValue;
GUIContent label = new GUIContent("Color");
//this call gives me a red line under every paramater even though they should all be what it needs
myColor.tertiaryColor = (TertiaryColorEnum)EditorGUILayout.EnumPopup(label, myColor.tertiaryColor,
showEnumValue, true);
//these ones work just fine (other parameter sets for the method)
myColor.tertiaryColor = (TertiaryColorEnum)EditorGUILayout.EnumPopup(myColor.tertiaryColor);
myColor.tertiaryColor = (TertiaryColorEnum)EditorGUILayout.EnumPopup("hi", myColor.tertiaryColor);
myColor.tertiaryColor = (TertiaryColorEnum)EditorGUILayout.EnumPopup(label, myColor.tertiaryColor);
// my custom function
public static bool ShowEnumValue(TertiaryColorEnum tertiaryColorEnum)
{
if(myColor.primaryColor == PrimaryColorEnum.Red)
{
if(tertiaryColorEnum == TertiaryColorEnum.Purple)
return false;
else
return true;
}
}
My best guess is that I'm doing something wrong with the Func parameter it wants, but I don't see how. Any help or ideas would be greatly appreciated!
Your ShowEnumValue has to accept an Enum. You can then cast the Enum to TertiaryColorEnum within the function and operate on it, but otherwise your function doesn't match the Func< Enum, bool> prototype, so the compiler matches the call to the next appropriate prototype:
public static Enum EnumPopup(string label, Enum selected, params GUILayoutOption[] options);
It's like if you had a delegate that accepted a specific type/class (e.g. Animal) and you tried to give it one that accepted a derived class (e.g. Lion) - the delegate expects a function that can handle crocodiles too!
Some reading on the topic of Covariance and Contravariance if you're interested.
I am new to c# and a little confused about how the out parameter modifier works.
I have this function
public static void GuidUnsmash(string smashed, out Guid first, out Guid second)
{
if (smashed.Length != 64)
{
throw new ArgumentOutOfRangeException();
}
string firstGuid = smashed.Substring(0, 32);
string secondGuid = smashed.Substring(32, 32);
first = new System.Guid(firstGuid);
second = new System.Guid(secondGuid);
}
which im trying to call using this
[HttpGet]
public async Task<ActionResult> Pending(string pendingticket)
{
// CAR-AAR built with PersonId and MonerisID in ticket, this was overkill, just needed the MonerisID
GuidHelpers.GuidUnsmash(pendingticket, out Guid personId, out Guid monerisId); //this is the line that has the error
var preload = await MonerisApplicationRepository.PrepareTransactionForMonerisPreload(monerisId);
var preloadResponse = await MonerisRepository.PostPreloadTransactionRequest(preload);
var persistPreload = await MonerisApplicationRepository.PersistMonerisPreloadTransactionResponse(monerisId, preloadResponse);
var transactionRequest = preloadResponse.ToMonerisPreAuthorization();
//var viewPendingRequest = new MonerisPendingPreloadTransaction(transactionRequest, preload);
// View redirects to Moneris with autosubmit to begin preauthorization process.
return View(transactionRequest);
}
However i am getting an error that says that there is no overload method for GuidUnsmash. Which is confusing me because they both have the same amount of parameters.
Normally, parameters used in function calls are "passed-by-value". The other option is for parameters to be passed-by-reference.
Keyword ref forces a parameter to be passed-by-reference. But that does not mean the function will actually do anything with the variable. It may or it may not.
Keyword out forces a parameter to be passed-by-reference and also that the value has to be assigned in the function. This can have ramifications for stuff like readonly variables which need a assignment. And so the caller is aware the value will not stay the same.
Keyword in is relatively new syntax, related to 'ref' and 'out'. It forces a parameter to be passed-by-reference but also prevents any reassignment of the value (like a inverted out). However I am somewhat unsure why you would use it.
In langauges that use naked pointers, usually naked pointer is used instead of ref. And there are no in or out keywords.
As for overloading:
The in, ref, and out keywords are not considered part of the
method signature for the purpose of overload resolution. Therefore,
methods cannot be overloaded if the only difference is that one method
takes a ref or in argument and the other takes an out argument.
Which means the error make no real sense.
So that leaves one hard-to-debug issue: the code is so broken somewhere before or between those two code piece, the compiler has issues even still telling you where the error is.
I've searched and tried many things but I'm not really fully happy.
While converting an old project from VB.Net to C# I found that the behaviour between the 2 languages is very different and breaks the logic in C# if not dealt with.
Consider an enum like:
public enum TestEnum
{
Val1 = 1,
Val2 = 2
}
I have this code in VB.Net
// Will contain 1
txthMyHiddenField.Value = TestEnum1.Val1
And also
// Will contain ~/Something?var=1
Dim Url As String = "~/Something?var=" & TestEnum1.Val1
In C# this would have the first case having Val1 and on the second case "~/Something?var=Val1"
The solution so far I could come up with without redesigning lots of code is to go everywhere and do something like:
= myEnum.ToString("d");
// Or
= ((int)myEnum).ToString();
// Or an extension.
I also considered creating an enum "class" but then I would have to change all switch statements, which is an even worse solution.
Am I missing something? Is there a cleaner way?
Why not simply
var url = "~/Somethimg?var=" + (int)myEnum;
For what it's worth, maybe this extension helps:
public static class EnumExtensions
{
public static int AsInt<TEnum>(this TEnum enumType) where TEnum : struct, IConvertible
{
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("TEnum must be an enum type");
return ((IConvertible)enumType).ToInt32(null);
}
}
var url = "~/Somethimg?var=" + myEnum.AsInt();
#Rivers,
I added a comment requesting more info in #Tim Schmelter's post but will try to provide a solution in the mean time.
#Eric, is correct in that it appears to come down to the explicit nature of C#. I also agree with #THG that if there is any change of repeatedly requiring this conversion, then an extension method is the cleanest way to go.
I haven't found a way to explicitly filter for enum, so I would be very interested in how such an extension method could be implemented.
In my case, I have limited type filtering and perform runtime validation. (I would obviously prefer compile time):
public static string ToIntString<T>(this T enumVal) where T : struct, IConvertible, IComparable, IFormattable
{
TestGenericEnum<T>();
return (Convert.ToInt32(enumVal).ToString();
}
private static void TestGenericEnum<T>()
{
if (!typeof(T).IsEnum)
throw new ArgumentException("T must be of type System.Enum");
}
Update: Tossed in IComparable, IFormattable restrictions per #Preston's advice.
Update 2: Bone headed move, can't cast int directly, need to use Convert class.
I'm writing a pathfinding algorithm for a game, but trying to keep it generic so it can be used in future applications.
I have a Node class which holds X, Y and "PassableType".
The NodeGrid class stores an array of Nodes, containing the graph information of how they connect, and then has a FindAStarPath() function, which takes as its parameters StartNode, EndNode, and params for "PassableTypes".
My problem is determining what type "PassableType" should have.
Ideally what I want is to be able to use a generic enum - i.e. a restricted list which each game defines. The Node will hold a single element of that list, to say what path type it is (the current game may use Path, Grass, Wall, etc)
Thus, when an entity tries to path, it provides the pathfinding function which types to treat as "passable". So a man may use
FindAStarPath(CurrentNode, DestinationNode, "Path", "Floor", "Door");
but a car may just use
FindAStarPath(StartNode, EndNode, "Road");
My problem is I can't work out how to get the NodeGrid to take a Generic enum or equivalent logic.
At the moment I have it taking strings, but this means I have to write
MyEnum.Road.ToString()
every time I use it.
Ideally I'd like to do something like
NodeGrid<MyEnum> CurrentNodeGrid = new NodeGrid<MyEnum>()
And then Nodes will take a MyEnum for their passableType, as will the pathfinding functions, thus allowing each game to have a different set of tile types for pathing.
But I can't define NodeGrid as:
public class NodeGrid<T> where T:enum
For clarity, the only part of the pathfinding function which uses this enum is this (contained within Node):
public bool IsPassable(string[] passableTypes)
{
for (var i = 0; i < passableTypes.Count(); i++)
{
if (this.PassableType == passableTypes[i]) return true;
}
return false;
}
Thanks
Haighstrom
Unless you're using some specific functionality of enums (like Enum.Parse), then I don't see any reason to constrain it to them. By freeing constraints, callers can use whatever types they see fit, beit enum, or a set of string values (as you currently have it), or a set of custom class instances to check against.
public class NodeGrid<T>
{
public T PassableType { get; private set; }
public bool IsPassable(params T[] passableTypes)
{
return IsPassable((IEnumerable<T>)passableTypes);
}
public bool IsPassable(IEnumerable<T> passableTypes)
{
foreach(T passType in passableTypes)
{
if (EqualityComparer<T>.Default.Equals(this.PassableType, passType))
return true;
}
return false;
}
}
But since we're now using generics, you can't use the == comparison anymore. The simplest is to leverage the EqualityComparer.Default utility. The main reason to use this over directly calling this.PassableType.Equals(passType) is it will perform null checks and leverage generics properly where applicable and if the types implement IEquatable<T>, then use those generic versions. Probably some other minor things. It will usually eventually call the Object.Equals overload.
Some examples based on your question:
//using a custom enum, calls the params T[] overload
NodeGrid<MyCarEnum> carNode = ...
carNode.IsPassable(MyCarEnum.Road, MyCarEnum.Tunnel);
//demonstrates receiving a set of pass types strings from an external source
List<string> passTypes = new List<string>("Path", "Floor", "Door");
NodeGrid<string> personNode = ...
personNode.IsPassable(passTypes) //calls the IEnumerable<T> overload
//feel free to declare enums wherever you want,
//it can avoid potential mixups like this:
NodeGrid<string> airplaneNode = ...
NodeGrid<string> personNode = ...
NodeGrid<MyCarEnum> carNode = ...
airplaneNode.IsPassable("Floor"); //makes no sense, but will compile
personNode.IsPassable("Clouds"); //makes no sense, but will compile
carNode.IsPassable("Sky"); //compile error: was expected a MyCarEnum value
I'd like to restrict the value of a number parameter in a constructor to within a certain range.
I know the conventional way is to do something like the following:
public class Foo
{
public int MaxAmount { get; }
public int Amount { get; set; }
public Foo(int amount)
{
if (amount > MaxAmount) { Amount = MaxAmount; }
else if (amount < 1) { Amount = 1; }
else { Amount = amount; }
}
}
But what I don't like about this is that the caller doesn't know when the property gets set to something other than what was specified. I could return an exception instead of silently clamping the value, but that's not very friendly.
What I'd like is something akin to this:
public Foo(int(1, this.MaxAmount) amount) // Where int(minimumValue, maximumValue)
{
Amount = amount;
}
in which one wouldn't even be able to instantiate Foo with an unacceptable value - the framework would prevent it.
Is anything like this possible?
EDIT FOR CLARITY:
What I'm after is a means by which the parameter itself can carry and communicate the information about its constraints - in a 'baked in' fashion which might, for example, surface in Intellisense when you wrote the call. So, I'd avoid the work of even attempting to instantiate the class if the values for the parameters were not valid.
If, for example, the program is running and the user types a number (N) and presses a button which creates a new Foo with an illegal quantity of N, I now have an exception to handle and something to debug and fix. Why even allow it in the first place? If Foo has been explicitly defined as having an upper boundary of 4 for its Amount property, what's the point of allowing the developer to write Foo(5) when I could have informed him that the value he's passing is not valid at the time that he wrote it?
If there's some syntactic sugar, like ParameterConstraint or something, that is handled by the Framework for me so that I don't have to roll my own into every class I write, I think that would be very useful.
I could return an exception instead of silently clamping the value, but that's not very friendly.
Say what? What do you mean, "friendly"? The caller isn't your friend, it's another piece of code that is trying to set an out of range value. The developer who wrote the code should be told immediately that he's doing something wrong.
Throw an exception!
You can do this using static-contract checking with Code Contracts (Premium only - The standard edition only offers runtime contract checking).
The syntax is simply
public Foo(int amount) {
Contract.Requires(amount < MaxAmount);
...
}
(Requires) contracts are evaluated by checking that the arguments is constrained when calling the method. In your instance, it will be difficult to evaluate the constructor argument with against the instance field MaxAmount, because you cannot check that value beforehand. (Make MaxValue static to solve this).
Example of such call.
int val = _getFromSomewhere();
var foo = new Foo(val);
//This May produce compile time error
// because the contract checker cannot prove you contract is met.
The fix would be to make sure you put the constraint where you call is made.
int val = _getFromSomewhere();
if (val < Foo.MaxAmount)
var foo = new Foo(val);
//Will always compile fine, because contract is met.
When you install Contracts, the static checker isn't turned on by default. Your project properties will have an extra tab where you can configure the contract options and enable static checking.
You will need to wrap the parameter up in a new type then. ints know what their max amount is, and it is int.MaxValue. If it is truly the case that the parameter itself knows its own max amount, and that it isn't something specific to class Foo, then you will need to create another type that checks the amount passed in to it. As it stands, the signature of Foo's constructor accepts any int data structure.
Either throw the exception or provide a static property to validate the amount
public static bool ValidateAmount(int amount)
{
if(amount > MaxAmount)
return false;
return true;
}
Not for sure if this works for properties types in C#, but you might be able to define an enumeration contain all of the acceptable values and then set the data type of the property to that enumeration. That would force the caller to use the enumeration and thus know what values are acceptable. Of course, if you have a lot of values in the acceptable range, the enumeration would be unwieldy.