I'm using an API that has a method that requires this type of argument:
System.Collections.ObjectModel.Collection<GenericTickType> genericTickList
How do I instantiate an object for that argument? Here's what I've tried but it keeps saying that the method call has some invalid arguments.
List<TickType> ticks_to_get = new List<TickType> { TickType.Price };
I've tried instantiating a Collection directly instead of a List and that doesn't seem to work.
"I've tried instantiating a Collection directly instead of a List and that doesn't seem to work."
What error do you get? You can definitely create an instance of Collection<T> directly, it is not an abstract class and it has several public constructors, including one that's parameter-less. You can do this, for example:
var values = new System.Collections.ObjectModel.Collection<int> { 1,2,3,4 };
I noticed your sample code has a GenericTickType and a TickType. Is this a mistake or do you actually have two classes? You said it's an enum (which one?), so one cannot possibly derive from the other. If they are two enum types, Collection<GenericTickType> and Collection<TickType> are two different classes and one is not assignable to the other.
Now, if TickType is castable to GenericTickType (and they probably are if they are both enums, and assuming they share the same numeric values), you still cannot cast Collection<TickType> to Collection<GenericTickType>. There's no contra/co-variance in C# for most classes yet (coming in C# 4). But you could cast each TickType by doing something like this:
List<GenericTickType> list = new List<GenericTickType> { (GenericTickType)TickType.Price };
list.Add((GenericTickType)TickType.Price); // add more...
Collection<GenericTickType>genericTicks = new Collection<GenericTickType>(list);
If you already have a List<TickType> and have access to C# 3.0 and LINQ, you can do this:
List<TickType> ticks = new List<TickType> { TickType.Price };
list.Add(TickType.Price); // add more...
List<GenericTickType> castedList = ticks.Cast<GenericTickType>().ToList();
Collection<GenericTickType>genericTicks = new Collection<GenericTickType>(castedList);
This uses the LINQ Cast<T>() and ToList<T>() extension methods to cast each TickType in the original list to GenericTickType and creating a new List<GenericTickType> which is used to instantiate the Collecion<GenericTickType>. (I avoided using var so you could see the types in each step).
You can't pass a List<> as a Collection<>
Maybe you have problems with covariance/contravariance? You have to do the cast on your own:
List<TickType> ticks_to_get = new Collection<TickType> { TickType.Price };
genericTickList = (Collection<GenericTickType>) ticks_to_get;
Look at Dave Bauman's answer ... unless TickType.Price doesn't return an object of type TickType it will not work
EDIT: Since GenericTickType is an enum - which API are you using? Is it of your company - can you change it? It seems to be strange that you are asked to pass a collection of enum values. See, if you can change the enum to a flagged enum ... and then pass the required values by combining them with the or-operator.
What is the type of GenericTickType? Is it an enum or class? I am assuming enum. If that is the case, modify your code as such:
Collection<GenericTickType> ticks_to_get = new Collection<GenericTickType>() { GenericTickType.Price };
The above works on 3.5 framework.
You can't use {} to initialize a Collection. You can do something like this, however:
List<TickType> ticks_to_get =
new List<TickType>( new TickType[] { TickType.Price });
or
List<TickType> ticks_to_get = new List<TickType>();
ticks_to_get.Add(TickType.Price);
Related
I know I can name parameters when I create a tuple implicitly like:
var me = (age: 21, favoriteFood: "Custard");
Is it possible to name parameters when a tuple is created explicitly? i.e.
var me = new ValueTuple<int, string>(21, "Custard");
No, you can't. The ValueTuple types are actually independent of the named field support in C#. The latter works more like named properties for anonymous types. That is, the compiler analyzes the code and generates aliases to the appropriate members according to your declarations and usages. It is through the assignment that the compiler learns the names of the fields. Since the basic constructor syntax doesn't provide a mechanism to name the fields, you can't use that to directly generate a tuple with named fields.
Of course, there are ways you can re-interpret the value returned from the constructor syntax, to assign names to that returned value. I'm assuming you're aware of that approach and are looking for something more direct.
As an example of what I mean by "re-interpret", you could do something like this:
static (int value, string text) ConvertToNamed((int, string) t) => t;
then this would name the fields, in a new variable:
var t1 = new ValueTuple<int, string>(21, "hello");
var t2 = ConvertToNamed(t1);
The variable t1 is stuck with Item1 and Item2. But the compiler will implicitly generate the desired names for the variable t2.
Maybe a better example is one where you don't require the additional method:
(int value, string text) t = new ValueTuple<int, string>(21, "hello");
Again, you're not really naming the fields in the constructor syntax, but they are reinterpreted by the local variable declaration.
This is probably not a serious limitation. In a scenario where there's a desire to have a persistent, easily-assigned name, it's probably better to declare a user-defined type than to use the tuple syntax anyway. You can write deconstructors for user-defined types as well, and declaring types like that means the names are first-class citizens when it comes to reflection, dynamic, etc.
You can cast to named tuple during assignment:
var me = ((int value, string text)) new ValueTuple<int, string>(21, "Custard");
Was looking for this when using ValueTuple in Linq. I did a F2-rename variable and it created the following syntax:
var query = from x in myList
select (First: x.something, Second: x.other) into g
select new Whatever(g.First, g.Second);
... C# 7.0 doesn’t enable the use of custom item names when using the
explicit System.ValueTuple<…> data type. Therefore, if you replace var
in Example 8 of Figure 1, you’ll end up with warnings that each item
name will be ignored.
Source
I'm posting this answer because the closest the docs come to explaining this is:
Data members of ValueTuple types are fields. Data members of Tuple
types are properties.
I don't believe so. Here are docs that I found on ValueTuple:
https://learn.microsoft.com/en-us/dotnet/api/system.valuetuple-7?view=netframework-4.7
I personally have not used the ValueTuble type. I have used the Tuple class before like this:
var tuple = new Tuple<int, string>(21, "Custard");
var number = tuple.Item1;
var st = tuple.Item2;
However I find using Tuples, especially when passed thru methods to be clunky. Always having to know what is in Item1 and Item2 etc. According to the ValueTuple docs, it is used in the same way.
Shouldn't you just make an entity class?
I have used the Anonymous Type which I think will suit your needs.
var anyom = new
{
age = 21,
favoriteFood = "Custard"
};
number = anyom.age;
st = anyom.favoriteFood;
I am attempting to use reflection to enumerate class fields and methods in order to do some automation in a web application. I am also abstracting this so that I could pass in any class.
Is there a way I could somehow pass in the type directly to a function to enumerate on rather than an instance of the type?
I would like the caller side to look like this:
var m = new MyClass(AClassOfSomeTypeIDefined);
I would like to avoid creating an instance as that is misleading to anyone who might use the class (as the instance isn't directly used).
using System;
public void UseType(Type t) {
// do something with t using reflection techniques - e.g.
Console.WriteLine("compat with int? {0}", typeof(int).IsAssignableFrom(t));
}
Call it with C# typeof keyword and the data type you want to pass.
// Examples...
UseType( typeof(int) );
UseType( typeof(System.Int32) );
UseType( typeof(System.Windows.Controls.Button) );
UseType( typeof(IDisposable) );
UseType( typeof(WhateverTypeYouWant) );
System.Type is one of the cornerstones of reflection as you already know, so run with it.
Other notes
Depending on what you want to do with the type, the following peripheral details might be useful.
To create an instance of a Type at runtime without having used the new keyword at compile time, use the System.Activator class. e.g.
// Create a List of strings like: new List<string>();
var list = (List<string>) Activator.CreateInstance( typeof(List<string>) );
yes just use the Type of your class. There's two basic ways to get the type:
Foo foo = new Foo();
Type myType = foo.GetType();
Type myTyp2 = typeof(Foo);
You can use GetType() if you only know the type at runtime (more common with reflection), or typeof() if you know the type at compile time already.
In your example this would be i.e.
var m = new MyClass(typeof(Foo));
You can pass a Type object just like any other parameter.
class MyClass
{
public MyClass(Type yourType)
{
// do as you please with yourType
}
}
The call it:
var m = new MyClass(typeof(YourType));
[TestMethod]
public void TestMyGenericBaseClasses()
{
Type typeCrazy = ThisPartyIsTypeCrazyWOOT();
// How do I create a generic object?
MadnessOhYeah<typeCrazy> sanity = new MadnessOhYeah<typeCrazy>();
// How do I use a generic object after it has been created?
Assert.IsTrue(sanity.MyTrueFunction(), "this is sparta");
// How do I call a generic function generically?
bool result = MyFunction<typeCrazy>();
Assert.IsTrue(result, "I did not get my teeth whitened!");
}
Is there any way to make this compile? (ThisPartyIsTypeCrazyWOOT returns a Type) Because this is a test, we're not concerned about having to use reflection or anything, unless that's just absolutely crazy.
I'm getting the vibe that this isn't going to be possible though, and that our test functions will just have to be more specific.
You need Type.MakeGenericType Method. Then Activator.CreateInstance Method.
Update 2: The first example I posted still doesn't 100% answer the question, since it involves a cast to List<int>, which is a type that is known at compile time. Below is a reflection-only solution that illustrates how you can use a generic type knowing nothing about the type argument itself. But, as you can see, it's... well, disgusting ;)
Type userType = GetUserSuppliedType();
// Now let's say userType is T.
// Then here we are getting the type typeof(List<T>).
// But, of course, there's no way to have any such information in the code.
Type listOfUserType = typeof(List<>).MakeGenericType(new[] { userType });
// This is effectively calling new List<T>();
object listObject = Activator.CreateInstance(listOfUserType);
// Do you see how messy this is getting?
MethodInfo addMethod = listOfUserType.GetMethod("Add");
// We better hope this matches userType!
object input = GetUserSuppliedInput();
// I suppose we could check it, to be sure...
if (input == null || input.GetType() != userType)
{
throw new InvalidOperationException("That isn't going to work!");
}
// Here we are finally calling List<T>.Add(input) -- just in the most ass-
// backwards way imaginable.
addMethod.Invoke(listObject, new[] { input });
Update: OK, if you insist on doing this, here's an example of how it's possible—but very cumbersome!
Type genericListType = typeof(List<>);
Type listOfInt32Type = genericListType.MakeGenericType(new[] { typeof(int) });
object listObject = Activator.CreateInstance(listOfInt32Type);
List<int> list = (List<int>)listObject;
list.Add(1);
Generics can't quite work like this because a Type object could be anything. Consider this code:
var list = new List<int>();
list.Add(1);
The type of list in the above code is known to be List<int>, which defines what operations are legal on list such as Add(1).
Now consider this instead:
Type t = GetTypeFromIndeterminateSourceSuchAsUserInput();
var list = new List<t>();
list.Add(?);
When t is a Type object rather than the name of a type (like int) which the compiler can parse, it's not really possible to instantiate a generic type using that type—or rather, it's possible (see Andrey's answer), but you can't really use the resulting object in any sort of generic way.
Now, you might think that something like this ought to work:
Type t = typeof(int);
var list = new List<t>();
list.Add(1);
...but just because the value of t is known (by you) at compile time doesn't change the way things work in general.
Anyway, yes it's possible using reflection; but if you go down that path, you're committing to a pretty reflection-heavy solution. What I'm getting at is that in general it isn't a particularly realistic thing to do.
When I do a query that returns an anonymous type
var assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new {p.Asset, p.Asset.PropertyTbl};
Can I type the return to anything other than var?
You cannot* return an anonymous type because the caller would not know what type it is and wouldn't be able to use it.
If you want to return the results, you can create objects of a non-anonymous type:
IEnumerable<Foo> assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new Foo { Bar = p.Asset, Baz = p.Asset.PropertyTbl};
You can also use the Tuple type in .NET 4 if you don't want to create a custom class for your values.
* This is not strictly true - it is possible but you should avoid doing it. Here is a link anyway if you really want to.
You can use object or dynamic (in .NET 4.0) instead of var but don't expect to find a name to an anonymous type. In your case using var is better as it will preserve the strong typing at least until you leave the scope of the current method.
You could define a new class:
public class AssetProp
{
public virtual string Asset {get;set;}
public virtual string PropertyTbl {get;set;}
}
And then you can return it as that class:
IEnumerable<AssetProp> assets =
from Product p in Session.CreateLinq<Product>()
where bundles.Contains(p.ProductBundle)
select new AssetProp {p.Asset, p.Asset.PropertyTbl};
Not really, since the new {p.Asset, p.Asset.PropertyTbl} code creates an anonymous type. Even using object doesn't really gain you much since you can't cast it to anything useful later on, so you would have to use reflection to access the properties.
Not really. If you cast to object you wont be able to access the properties of your anonymous class.
The var keyword was specifically introduced for dealing with anonymous classes - why would you want to avoid it? If you need to return the data you should name the class.
You can if you use lambda expressions, otherwise you can do a cast but do some good exception handling.
you can also do this (it does relate much to your problem though, because you just move "var" somewhere else, but it's interesting that it recognize those types as same)
var element = new { id = 7 };
List<object> collection = new List<object>();
element = collection.Select(item => new { id = 0 }).First();
Consider the following:
// select a subset of the DataTable
var subset = DataTable.Where(...).Select(row => new
{
Id = Convert.ToInt32(row["Id"]),
Name = row["Name"].ToString(),
Email = row["Email"].ToString()
});
// or create a new object
var subset = new {
Id = 1,
Name = "something random",
Email = "name#domain.tld"
};
Is there any way to use the subset variable as a parameter to a method, without it being cast as a plain Object? Can you somehow carry the auto-generated type of the variable?
I am trying to avoid having to create new classes every time I want to pass LINQ subsets to methods.
Random generic approaches are welcome.
No, passing anonymous types about isn't generally a good idea because you lose the type information*. You should create a concrete type and use that instead.
var subset = DataTable.Where(...).Select(row => new SomeType
{
Id = Convert.ToInt32(row["Id"]),
Name = row["Name"].ToString(),
Email = row["Email"].ToString()
});
Alternatively you can use the Tuple type if you are using .NET 4. This is a simple way to create "disposable" types and still get some type-safety.
*Actually there is a workaround, but I regard it is an ugly hack and would advise that you don't do it.
If I need to do this, I use resharper's "Replace Anonymous Type With Named Class" refactoring option. Then you have an appropriate named type to expose over the API, and you haven't had to do any work. This also gives you options to create it immutable (like anonymous types) or mutable, nested vs top-level, etc.
BTW, I don't recommend struct here (from the question).
Another option is to pass the behaviour into the method - i.e. an Action<int,string,string> callback - then do something like:
foreach(item in query) callback(item);
However, I don't like this as it is not obvious that there is a likely error in:
DoSomething(args, (id, email, name) => Email(To: email, Subject: name));
(the error being that it should probably be (id, name, email), if you see what I mean)
You can use a generic method:
public static void Foo<T>(T item)
{
// Do whatever
}
Then if you call
Foo(subset);
the compiler will infer T for you. Whether or not that actually helps you is another matter... it depends on what the method is meant to do. Obviously Foo can't refer to Id, Name, Email etc.
In general, if multiple methods should know about the same members, then you should use a named type. The usual case for passing them to generic methods is where the method really doesn't care about what type is involved, such as in LINQ.
I've made a feature request for C# 5 that we should be able to create types which have all the same features as anonymous types (immutability, equality, hash code generation, ToString dumping) but for simple named types. We'll see if it actually happens...
Anonymous Types don't provide much help outside of the context they where created.
If you need to pass an Anonymous Type to a method, either this method is very generic like (Example)
void PrintAllObjectProperties(object obj);
witch you would use reflection to do the work, or you are doing something wrong.
Here's what I came up with...
Extension method on Object:
public static class ObjectExtensions
{
/// <summary>
/// Cast Object to anonymous type.
/// E.G.: new Object().ToAnonymousType(new { Property = new Type() });
/// </summary>
public static T ToAnonymousType<T>(this Object o, T t)
{
return (T)o;
}
}
Usage:
public void HandleAnonymousTypeAsParameter(Object o)
{
var anonymousType = o.ToAnonymousType(new
{
Id = new Int32(),
Foo = new String(),
Bar = new String()
});
// ... You can do this in even less characters:
var anonymousType = o.ToAnonymousType(new { Id = 0, Foo = "", Bar = "" });
}
HandleAnonymousTypeAsParameter(new
{
Id = 1,
Foo = "foo",
Bar = "bar"
});
Credits goes to John Skeet and Thomas P.