Say i have the following method:
private void something()
{
string text = "This is obviously a string";
dynamic pietje = Guid.NewGuid();
var dict = new Dictionary<Guid, string>();
dict.Add(pietje, text);
var someText = dict[pietje];
}
The image below shows IntelliSense still thinks it is a dynamic even though i do not see how this could be anything other than a string (or null)
Am I missing a setting or is there something preventing IntelliSense from knowing someText should be a string? I might be leaning on IntelliSense a bit too much, but it gets quite difficult for some objects to manually type the entire method or property name correctly.
So what is the reason for this? And is there something I can do to resolve this?
obviously I could fix it in many ways:
string someText = dict[pietje];
var someText = dict[(Guid)pietje];
var someText = dict[pietje] as string;
etc.
But that is not the point nor what I want.
This issue crops up in many scenarios. Classic question in SO:
public string Foo(string fooable) { .... }
dynamic fooable = "whatever";
var whyAmIDynamic = Foo(fooable);
Huh? Why is wyAmIDynamic dynamic?!? The compiler should know that wyAmIDynamic is string, shouldn't it?
Yes, but then someone else comes along and writes the following:
public int Foo(int fooable) { .... } //a new overload of Foo
And now, what should Foo(fooable) return? dynamic seems to be the only reasonable option; a method call involving a dynamic argument can't be resolved until runtime.
In your specific case, the compiler has no reason not to believe that someone might come along and implement the following absurd overload to Dictionary<TKey, TValue>:
public int this[string key] { ... }
Does this overload make any sense? No. Is it the compilers business to figure out if it makes sense? No. Is it legal? Yes, therefore the indexer returns a dynamic variable.
Because pietje is dynamic, the result of the execution of var someText = dict[pietje]; is determined on runtime. Until that time, the correctness and outcome of that call is unknown, hence dynamic.
I guess you meant to use var here, since you know the type of pietje on beforehand.
As said in a comment: You go by the simple rule that all dynamic evaluations are done on runtime. You can type in an invalid field name and still let it compile.
You are specifying the Dictionary to be of type Dictionary<Guid, string>. When you try to read, you're using a dynamic as the key for the dictionary, not even knowing if this is would be a valid statement.
There's a relative easy way of fixing this issue:
Address the key in the dictionary with the same type as the declaration
string text = "This is obviously a string";
dynamic pietje = Guid.NewGuid();
var dict = new Dictionary<Guid, string>();
dict.Add(pietje, text);
var someText = dict[(Guid)pietje];
//Of course you could go about casting this in numerous ways
Related
I've seen that people have asked similar questions but they're normally using complex types and resolve to use interfaces instead. What I would like to do is pass back either list, list or list depending on an enum. Something like this:
private IList<T> GetValueFromType<T>(MyData data)
{
switch (data.SomeType)
{
case MyType.Percent:
var PercentValues = new List<double>();
PercentValues.Add(data.CompAPercentage);
PercentValues.Add(data.CompBPercentage);
return (T)PercentValues;
case MyType.Money:
var MoneyValues = new List<decimal>();
MoneyValues.Add(data.CompAMoney);
MoneyValues.Add(data.CompBMoney);
return (T)MoneyValues;
case MyType.Months:
var MonthValues = new List<int>();
MonthValues.Add(data.CompAMonth);
MonthValues.Add(data.CompBMonth);
return (T)MonthValues;
}
}
This shows an error on all 3 return statements saying the type can't be converted to 'T'. Is this possible / advised or is this a code smell?
You basically can't do this.
It is possible to circumvent the static type-checking as Mike's answer says in order to make GetValueFromType<T> compile, but how will you invoke it? Your calling code will need to specify T, eg.
var myValue = GetValueFromType<int>(myData)
because there's no way to infer T from the call itself, and when the method tries to return a list which doesn't match your choice of T you'll get an InvalidCastException. Given that you need to interrogate MyData to find out how to call this method safely, you might as well have the switch in the calling code.
This is somewhat dangerous because it loses some of the power of static type checking and is easy for callers to get wrong. The compiler will flag it. You may need to insert an (object) cast to tell the compiler you really want to make the cast:
return (IList<T>) (object) MonthValues;
I have some reflection code and I would love to have a way of binding the method names to types instead of declaring through strings.
I have this interface:
interface IDoStuff<T> {
void Do(T stuff);
}
Then I have this code:
object stuff = GotThisFromSomewhereElse();
object doer = GotThisFromSomewhereElseAlso();
var doMethodInfo = doer.GetType().GetMethod("Do");
doMethodInfo.Invoke(doer, new[] { stuff });
The problem is that I can't simply do a safe cast and call it because it's generic and I don't actually know what type T is.
This works fine but when I rename the method I have to go update this, I'm not overly concerned as I have tests to confirm all of this works which protects against not knowing it changed.
It's just really ugly and I was curious if there is some slick way to have this typed and thus will get renamed by ReSharper if I change it.
I'd really like something like:
object stuff = GotThisFromSomewhereElse();
object doer = GotThisFromSomewhereElseAlso();
var doMethodInfo = doer.GetType().Methods.Do;
doMethodInfo.Invoke(doer, new[] { stuff });
Thanks in advance and please let me know if this is something that is possible in C#.
Starting with C# 6, you'll be able to avoid the magic string using the new nameof statement:
IDoStuff<object> dummy = null; // don't need a valid instance.
string methodName = nameof(dummy.Do) // yay! no magic strings.
EDIT: #31eee384 pointed out in the comments that the above can be further simplified like this:
string methodName = nameof(IDoStuff<object>.Do);
About the new nameof statement, the documentation has this to say, which seems very much in line with what OP is trying to accomplish:
you often want to capture the string name of a method. Using nameof helps keep your code valid when renaming definitions. Before you had to use string literals to refer to definitions, which is brittle when renaming code elements because tools do not know to check these string literals.
Before C# 6, it's also possible to avoid magic strings by using expressions, but it's a little clunkier. Here is an example that would work in your case.
First, you write the following extension method:
public static string GetMethodName<T>(this T instance, Expression<Action<T>> methodExpression)
{
if (methodExpression.Body is MethodCallExpression)
{
return ((MethodCallExpression)methodExpression.Body).Method.Name;
}
else
{
throw new ArgumentException(string.Format("Invalid method expression: {0}", methodExpression.Body));
}
}
And then you can use it like this:
IDoStuff<object> dummy = null; // don't need a valid instance.
string methodName = dummy.GetMethodName(t => t.Do(null)); // yay! still no magic strings.
Create generic method DoIt:
private void DoIt<T>(T stuff, IDoStuff<T> doer) {
doer.Do(stuff);
}
and call it:
DoIt(GotThisFromSomewhereElse(), GotThisFromSomewhereElseAlso());
Of course, GotThisFromSomewhereElseAlso and GotThisFromSomewhereElse should be generics as well.
I have some methods that take 20 or more strings as parameters. I was wondering what works better: passing 20 string parameters to the method or putting them all in a dictionary and passing it as only parameter.
Multiple strings:
public Boolean isNice(string aux, string aux2, string aux3, string aux4, string aux5, string aux6, string aux7,
string aux8, string aux9, string aux10, string aux11, string aux12, string aux13, string aux14, string aux15, string aux16)
{
string foo1 = aux;
string foo2 = aux2;
// etc
return true;
}
public void yeah()
{
string aux = "whatever";
string aux2 = "whatever2";
// etc
isNice(aux, aux2, ..., ..., ...);
}
Dictionary of strings
public Boolean isNice(Dictionary<string, string> aux)
{
string foo1 = aux["aux1"];
string foo2 = aux["aux2"];
// etc
return true;
}
public void yeah()
{
string aux = "whatever";
string aux2 = "whatever2";
// etc
Dictionary<string, string> auxDict = new Dictionary<string,string>();
auxDict.Add("key1", aux);
auxDict.Add("key2", aux2);
// etc
isNice(auxDict);
}
My question is regarding performance, readability and code simplicity.
Right now I'm using multiple strings: should I use dictionaries instead?
This depends. Are all 20 parameters required for the function to work?
If so, create a data type that can communicate all 20 values and pass in an instance of that data type. You could create helper classes to easily initialize that type of object. You can easily pass in a new instance of that data type, and provide flexible ways to initialize the type:
isNice(new niceParams
{
aux1 = "Foo",
aux2 = "Bar"
// ...
}
);
If not, put the optional parameters at the end of the signature, and give them default values.
public Boolean isNice(string req1, string req2, string optional1 = null)
This way, you have overloads to specify exactly which values you want to provide.
Another benefit of this is you can used named parameters to call the function:
isNice(req1, req2, optional1: "Foo", optional15: "Bar");
With that said, I would not use a dictionary. It forces the caller to understand the signature, and completely breaks any compiler type safely. What if required values aren't provided? What if a key is misspelled? All this checking has to now be done at runtime, causing errors that can only be caught at runtime. To me, it seems to be asking for trouble.
The main difference is that in case when you have 20 string parameters the compiler will ensure that all of them are explicitly set, even if they are set to null. In case of passing a collection the compiler will not be able to detect that somebody has forgotten to set the aux17 parameter: the code that uses a dictionary-based API would continue to compile, so you would be forced to add an extra check at run-time.
If it is OK with your code to not have a compiler check, for example, because all your string values are optional, then a collection-based approach is easier to maintain.
The difference in speed cannot be predicted until you implement the change. A collection-based approach would perform an additional memory allocation, so it would consume more CPU cycles. On the other hand, the difference may be too small to have a real impact on the overall performance of your program.
Note that since your parameters are named uniformly, it appears that they may be placed in a "flat" collection, rather than a dictionary. For example, you could make an API taking a list or an array of strings. In case of an array, you could also make your method take variable number of parameters, so that the callers could use the old syntax to call your method:
public bool isNice(params string[] args)
Recently I saw a person heavily using var and default keywords for declaration of variables (and for every declaration), something like this:
var employee = default(Employee); //Employee is a class
var errorInfo = default(ErrorInfo); //ErrorInfo is struct; Blank is default value
var salary = default(Double);
var isManager = default(Boolean?);
instead of using:
Employee employee = null; //Employee is a class
ErrorInfo errorInfo = Blank; //ErrorInfo is struct; Blank is default value
Double salary = 0.0;
Boolean? isManager = null;
or, instead of using even:
Employee employee; //Employee is a class
ErrorInfo errorInfo; //ErrorInfo is struct; Blank is default value
Double salary;
Boolean? isManager;
Now using var and default for declaration for every variable is something i am not accustomed to.
Want to know:
- If this is a recommended practice?
- Your views and preference?
PS:
- Have gone through Use of var keyword in C#, Use of "var" type in variable declaration and https://stackoverflow.com/questions/633474/c-do-you-use-var, however, think that this question although related is slightly different as it is solely around declaration/initialization and not around assignment.
- I understand the difference between snipped 2 and snippet 3. However, question is more around snippet 1.
- If you strongly feel that this question belongs to programmers stackexchange feel free to move.
I'm not going to say anything about "var" there have been comments and discussions about this in the past (sufficiently so ;-)
Concerning "default()" I would not use this to initialize a known type, but rather only in generics. There it helps to transparently handle value types or reference types by allowing you to provide a default (return) value or can be used in comparisons.
Well, the default keyword isn't the most used keyword I think, and in my opinion it serves its purpose best in terms of Generics, like so:
public class Foo<T>{
private T _instance;
public Foo<T>(){
_instance = default(T);
}
}
in order to get a new default instance of T.
There are really no reasons to use it like scenario 1 in your post.
Using var however is a different question, and many view this as a matter of readability. I default to var when I write code simply because I find it easier to read:
var me = new Person();
It seems a bit redundant in terms of readability to do
Person me = new Person();
Another case I recommend var is if something changes. Consider the following example:
public decimal Calculate(decimal one, decimal two){
return one + two;
}
And somewhere else in your code:
decimal d = Calculate(1M, 2M);
If you for some reason change the return type of Calculate to, say, double you need to change all the places where you strongly defined the variable.
If you instead do
var d = Calculate(1M, 2M)
you don't have to worry about this. The Double/Decimal example is a bit simple, but in terms of refactoring and interfacing out classes, I've found this very useful.
I think this is bad practice which will prevent the compiler (and 3rd party tools) from catching bugs related to failure to initialize a variable. Generally I try to keep declaration and assignment as close to each other as possible. Assigning values that aren't intended to be used to variables can potentially introduce subtle bugs that are difficult to catch. Normally I'd either:
SomeType variable1; //want to store something that will be out of scope later
using(blah)
{
//...
variable1=blah;
}
//use variable1 here
or assign required value immediately:
SomeType variable2 = new SomeType();
//use variable2 immediately
or (for me, more frequently nowdays)
var variable2 = new SomeType();
assigning null/placeholder values is mainly pointless.
I use var for assignment. However I always declare instances using the class. I generally also instantiate them at the time to avoid unexpected NullReferenceExceptions
The code is ok.
Just make sure that you don't copy this technique to initialize enums where 0 is not default value or flagged enumerations.
[Flags]
public enum MyFlags
{
Test = 1,
Test2 = 2
}
MyFlags flags = default(MyFlags);
Console.WriteLine(flags); // oops
I guess this could also be asked as to how long the created type name is attached to an anonymous type. Here's the issue:
A blog had something like this:
var anonymousMagic = new {test.UserName};
lblShowText.Text = lblShowText
.Text
.Format("{UserName}", test);
As sort of a wish list and a couple ways to go at it. Being bored and adventurous I took to creating an string extension method that could handle this:
var anonymousMagic = new {test.UserName, test.UserID};
lblShowText.Text = "{UserName} is user number {UserID}"
.FormatAdvanced(anonymousMagic);
With the idea that I would get the property info from the anonymous type and match that to the bracketted strings. Now with property info comes reflection, so I would want to save the property info the first time the type came through so that I wouldn't have to get it again. So I did something like this:
public static String FormatAdvanced(this String stringToFormat, Object source)
{
Dictionary<String, PropertyInfo> info;
Type test;
String typeName;
//
currentType = source.GetType();
typeName = currentType.Name;
//
//info list is a static list for the class holding this method
if (infoList == null)
{
infoList = new Dictionary<String, Dictionary<String, PropertyInfo>>();
}
//
if (infoList.ContainsKey(typeName))
{
info = infoList[typeName];
}
else
{
info = test.GetProperties()
.ToDictionary(item => item.Name);
infoList.Add(typeName, info);
}
//
foreach (var propertyInfoPair in info)
{
String currentKey;
String replacement;
replacement = propertyInfoPair.Value.GetValue(source, null).ToString();
currentKey = propertyInfoPair.Key;
if (stringToFormat.Contains("{" + currentKey + "}"))
{
stringToFormat = stringToFormat
.Replace("{" + currentKey + "}", replacement);
}
}
//
return stringToFormat;
}
Now in testing, it seems to keep the name it created for the anonymous type so that the second time through it doesn't get the property info off the type but off the dictionary.
If multiple people are hitting this method at the same time, is it pretty much going to work in a Session like fassion; IE the names of the types will be specific to each instance of the program? Or would it be even worse than that? At what point does that name get chucked and overwritten?
It never does. The type is generated at compile-time and you can consider it constant and unique throughout the life of the app-domain.
I question the value of this function though. The obvious first reason is because you don't have much of the functionality of the Format method on the String class (no escape for brackets, no formatting of values in the brackets, etc, etc).
The second is that it basically links the format string to the type being passed in, so they are not swapped out easily. If I had two classes which had the same conceptual value, but different properties naming it, I have to change my format string to display it with your method to compensate for the fact that the property name is embedded in the format string.
Anonymous types are generated at compile time, and so the reflection names should be static as long as you don't re-compile the assembly.
There is a detailed post here that describes the names, but I believe what you are doing is safe.
I have two things to say, but this isn't really an answer.
First of all, the Dictionary doesn't have to have a string key; the key could be the actual type. i.e. it could be a Dictionary<Type, Dictionary<String, PropertyInfo>>. That would be faster because you don't have to get the type name, and less error prone - what if I send that method two non-anonymous types with the same name but different namespaces?
Second, you should read Phil Haack's recent blog post about this subject. It contains a full implementation of such a method.