I want to override the default structure of KeyValuePair in C#, so that I can make a KeyValuePair to accept a 'var' types.
Something like this :
List<KeyValuePair<string, var>> kvpList = new List<KeyValuePair<string, var>>()
{
new KeyValuePair<string, var>("Key1", 000),
new KeyValuePair<string, var>("Key2", "value2"),
new KeyValuePair<string, var>("Key3", 25.45),
};
Even if its possible for dictionary, then also it will solve my problem.
You could use object as your type, and then cast to/from object to desired outcomes. However, it's important to note that this is very much the opposite of object oriented programming, and generally indicates an error in your design and architecture.
Hmm I am wondering if this might help you: To have a list as you want, it is really possible BUT the "var" type (as you named it) must be the same for all KeyValuePair instances. For having whatever type you must use object or dynamic (use Haney's answer).
So considering that you want a single type for all KeyValuePair instances, here is a solution:
Firstly, create this helper class:
public static class KeyValuePairExtentions
{
public static List<KeyValuePair<string, T>> GetNewListOfType<T>(Expression<Func<T>> type)
{
return new List<KeyValuePair<string, T>>();
}
public static void AddNewKeyValuePair<T>(this List<KeyValuePair<string, T>> #this, string key, T element)
{
#this.Add(new KeyValuePair<string, T>(key, element));
}
}
To consume these functions, here is an example:
var lst = KeyValuePairExtentions.GetNewListOfType(() => new {Id = default (int), Name = default (string)});
lst.AddNewKeyValuePair("test1", new {Id = 3, Name = "Keith"});
The ideea is to rely on the powerfull type inference feature that we have in C#.
Some notes:
1) if T is anonymous and you create a new instance of a list in an assembly and consume it in another assembly it is VERY possible that this will NOT work due to the fact that an anonymous type is compiled per assembly (in other words, if you have a variable var x = new { X = 3 } in an assembly and in another var y = new { X = 3 } then x.GetType () != y.GeTType () but in the same assembly types are the same.)
2) If you are wondering whether an instance it's created or not by calling GetNewListOfType, the answer is NO because it is an expression tree function and the function is not even compiled. Even with a Func will work because I am not calling the function in my code. I am using the function just for type inference.
Related
I'm trying to return all the properties of a class, and the return type of each property using Roslyn (not reflection..)
I've gotten close, but then I hit a property that returns an array of strings (or perhaps an enumeration?) I'm fighting with how to find out the type within the array/collection...
public class msgClass // part of a larger class, and referenced as Roslyn Document
string[] Lines {get; set;} //property in larger class of properties
...
var DocumentsInProject = await roslynUtilities.GetMembers<BasePropertyDeclarationSyntax>(msgClass);
foreach (var itemClassProperty in DocumentsInProject)
{
var itemDeclaredSymbol = semanticModelOfDoc
.GetDeclaredSymbol(itemClassProperty) as IPropertySymbol;
if (itemDeclaredSymbol == null)
throw new Exception($"property: {itemClassProperty}");
var name = itemDeclaredSymbol.Name;
//what does it return?
string returnType = string.Empty;
if (itemDeclaredSymbol.Type.IsReferenceType)
{
var typeofKind = itemDeclaredSymbol.Type.TypeKind;
var typeincollection = itemDeclaredSymbol.Type.BaseType;
var containingType = itemDeclaredSymbol.Type.ContainingType.Name;
}
else
{
returnType = itemDeclaredSymbol.Type.Name;
}
}
If it isn't obvious this is isn't production code - I'm hacking as I'm new to Roslyn, and I'm working on building a Visual Studio add-in that is reviewing classes in a project.
You actually need to convert property type symbol to INamedTypeSymbol or to IArrayTypeSymbol. You can check that the type is generic [un]bound type by INamedTypeSymbol and try to figure out the generic type parameters. It will allow to you receive collection's element type if type not just generic type, but collection. Casting to IArrayTypeSymbol will allow to you get array's element type. So your code should look like this:
...
if (itemDeclaredSymbol.Type is INamedTypeSymbol namedType && namedType.IsGenericType)
{
// use namedType.TypeArguments if type is bound generic or namedType.TypeParameters if isn't
}
else if (itemDeclaredSymbol.Type is IArrayTypeSymbol arrayType)
{
// use arrayType.ElementType as you want
}
...
I am having problem understanding the rationale and purpose for asObservable method in RxSwift's Observable class.
/// A type-erased `ObservableType`.
///
/// It represents a push style sequence.
public class Observable<Element> : ObservableType {
/// Type of elements in sequence.
public typealias E = Element
public func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
abstractMethod()
}
public func asObservable() -> Observable<E> {
return self
}
}
What's the purpose of asObservable when it's returning self?
Surely if you can run this method, you already have access to the object. Also, what does the "type-erased ObservableType" in the comment means?
I believe the answer is apparent if you look at the ObservableType protocol and what objects conform to it (namely things like subjects, etc.).
The only guarantee is that the object will return an Observable in response to a call to asObservable. While conformance is trivial for an Observable, it may be less so for subjects and other units. But this guarantee allows you to use all type that can provide an Observable together in the same operator chain.
In essence this is similar to Strings conformance to CustomStringConvertible.
You asked two questions:
1. What's the purpose of asObservable when it's returning self?
You almost don't need to ever use asObservable(). The only time I think you'd need is when you're assigning casting a Subject/Relay to an Observable.
Suppose you have a variable that is a BehaviorRelay. It can both, observe and be an observable.
ViewModel.swift
let deviceOrientation = BehaviorRelay<UIInterfaceOrientation>(value: UIApplication.shared.statusBarOrientation)
And then you have a variable that is not both but only an observable like below.
ViewController.swift
lazy var incorrect : Observable<UIInterfaceOrientation> = {
return self.viewModel.deviceOrientation // ERROR
}()
lazy var correct : Observable<UIInterfaceOrientation> = {
return self.viewModel.deviceOrientation.asObservable()
}()
Then you'd need to cast so you'd have the correct type.
The incorrect variable would give the following error:
Cannot convert value of type BehaviorRelay<UIInterfaceOrientation>
to closure result type Observable<UIInterfaceOrientation>
2. What does the "type-erased ObservableType" in the comment means?
I suspect Scott's comment is semi-correct. I mean for sure it's confusing. You can flatten the type of a BehvaiorRelay, PublishSubject to a Observable and then assign one Observable to another. Otherwise still they all require the associatedType to be given ie no type erasure happening.
let x : AnyHashable = 10
let y : AnyHashable = "Alex"
if x == y { print("equal" } // compiles!
var i = PublishSubject<Int>().asObservable()
var s = PublishSubject<String>().asObservable()
if i == s { print("equal" } // does NOT compile. Gives following error:
Binary operator == cannot be applied to operands of type
Observable<Int> and Observable<String>
I want to create a function object, which also has some properties held on it. For example in JavaScript I would do:
var f = function() { }
f.someValue = 3;
Now in TypeScript I can describe the type of this as:
var f: { (): any; someValue: number; };
However I can't actually build it, without requiring a cast. Such as:
var f: { (): any; someValue: number; } =
<{ (): any; someValue: number; }>(
function() { }
);
f.someValue = 3;
How would you build this without a cast?
Update: This answer was the best solution in earlier versions of TypeScript, but there are better options available in newer versions (see other answers).
The accepted answer works and might be required in some situations, but have the downside of providing no type safety for building up the object. This technique will at least throw a type error if you attempt to add an undefined property.
interface F { (): any; someValue: number; }
var f = <F>function () { }
f.someValue = 3
// type error
f.notDeclard = 3
This is easily achievable now (typescript 2.x) with Object.assign(target, source)
example:
The magic here is that Object.assign<T, U>(t: T, u: U) is typed to return the intersection T & U.
Enforcing that this resolves to a known interface is also straight-forward. For example:
interface Foo {
(a: number, b: string): string[];
foo: string;
}
let method: Foo = Object.assign(
(a: number, b: string) => { return a * a; },
{ foo: 10 }
);
which errors due to incompatible typing:
Error: foo:number not assignable to foo:string
Error: number not assignable to string[] (return type)
caveat: you may need to polyfill Object.assign if targeting older browsers.
TypeScript is designed to handle this case through declaration merging:
you may also be familiar with JavaScript practice of creating a function and then extending the function further by adding properties onto the function. TypeScript uses declaration merging to build up definitions like this in a type-safe way.
Declaration merging lets us say that something is both a function and a namespace (internal module):
function f() { }
namespace f {
export var someValue = 3;
}
This preserves typing and lets us write both f() and f.someValue. When writing a .d.ts file for existing JavaScript code, use declare:
declare function f(): void;
declare namespace f {
export var someValue: number;
}
Adding properties to functions is often a confusing or unexpected pattern in TypeScript, so try to avoid it, but it can be necessary when using or converting older JS code. This is one of the only times it would be appropriate to mix internal modules (namespaces) with external.
So if the requirement is to simply build and assign that function to "f" without a cast, here is a possible solution:
var f: { (): any; someValue: number; };
f = (() => {
var _f : any = function () { };
_f.someValue = 3;
return _f;
})();
Essentially, it uses a self executing function literal to "construct" an object that will match that signature before the assignment is done. The only weirdness is that the inner declaration of the function needs to be of type 'any', otherwise the compiler cries that you're assigning to a property which does not exist on the object yet.
EDIT: Simplified the code a bit.
Old question, but for versions of TypeScript starting with 3.1, you can simply do the property assignment as you would in plain JS, as long as you use a function declaration or the const keyword for your variable:
function f () {}
f.someValue = 3; // fine
const g = function () {};
g.someValue = 3; // also fine
var h = function () {};
h.someValue = 3; // Error: "Property 'someValue' does not exist on type '() => void'"
Reference and online example.
As a shortcut, you can dynamically assign the object value using the ['property'] accessor:
var f = function() { }
f['someValue'] = 3;
This bypasses the type checking. However, it is pretty safe because you have to intentionally access the property the same way:
var val = f.someValue; // This won't work
var val = f['someValue']; // Yeah, I meant to do that
However, if you really want the type checking for the property value, this won't work.
I can't say that it's very straightforward but it's definitely possible:
interface Optional {
<T>(value?: T): OptionalMonad<T>;
empty(): OptionalMonad<any>;
}
const Optional = (<T>(value?: T) => OptionalCreator(value)) as Optional;
Optional.empty = () => OptionalCreator();
if you got curious this is from a gist of mine with the TypeScript/JavaScript version of Optional
An updated answer: since the addition of intersection types via &, it is possible to "merge" two inferred types on the fly.
Here's a general helper that reads the properties of some object from and copies them over an object onto. It returns the same object onto but with a new type that includes both sets of properties, so correctly describing the runtime behaviour:
function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
Object.keys(from).forEach(key => onto[key] = from[key]);
return onto as T1 & T2;
}
This low-level helper does still perform a type-assertion, but it is type-safe by design. With this helper in place, we have an operator that we can use to solve the OP's problem with full type safety:
interface Foo {
(message: string): void;
bar(count: number): void;
}
const foo: Foo = merge(
(message: string) => console.log(`message is ${message}`), {
bar(count: number) {
console.log(`bar was passed ${count}`)
}
}
);
Click here to try it out in the TypeScript Playground. Note that we have constrained foo to be of type Foo, so the result of merge has to be a complete Foo. So if you rename bar to bad then you get a type error.
NB There is still one type hole here, however. TypeScript doesn't provide a way to constrain a type parameter to be "not a function". So you could get confused and pass your function as the second argument to merge, and that wouldn't work. So until this can be declared, we have to catch it at runtime:
function merge<T1, T2>(onto: T1, from: T2): T1 & T2 {
if (typeof from !== "object" || from instanceof Array) {
throw new Error("merge: 'from' must be an ordinary object");
}
Object.keys(from).forEach(key => onto[key] = from[key]);
return onto as T1 & T2;
}
This departs from strong typing, but you can do
var f: any = function() { }
f.someValue = 3;
if you are trying to get around oppressive strong typing like I was when I found this question. Sadly this is a case TypeScript fails on perfectly valid JavaScript so you have to you tell TypeScript to back off.
"You JavaScript is perfectly valid TypeScript" evaluates to false. (Note: using 0.95)
Say I'm defining a simple 2D point class in Scala, and I want to be able to construct it with various types:
class Point(x:Float, y:Float) {
this(x:Double, y:Double) = this(x.toFloat, y.toFloat)
this(x:Int, y:Int) = this(x.toFloat, y.toFloat)
// etc...
}
I want to boil this down using a template, such as:
class Point(x:Float, y:Float) {
this[T](x:T, y:T) = this(x.toFloat, y.toFloat)
}
I know this won't work anyway, since T could be a type for which toFloat isn't defined, but the compiler error I get is:
no type parameters allowed here
Is this just unsupported in Scala? If so, why, and is there any simple way to get around this?
Scala's class constructors (unlike Java's) can't take type parameters, only the class itself can. As to why Scala made this design choice, I assume the main reason is simplicity.
If you want a secondary "builder" method that is generic, the natural thing to do is define it on the companion object. For example,
object Point {
def build[T : Numeric](x: T, y: T) = {
val n = implicitly[Numeric[T]]
new Point(n.toFloat(x), n.toFloat(y))
}
}
class Point(val x:Float, val y:Float)
val p = Point.build(1, 2) // Companion object's builder
p.x + p.y
Here I've used the Numeric typeclass to get a generic toFloat method.
I played with this for awhile, getting as "close" as...
class Point(x:Float, y:Float) {
def this[T <: Any { def toFloat: Float }](x:T, y:T) = this(x.toFloat, y.toFloat)
}
...which results in "error: no type parameters allowed here" (just as per the post) and then I realized...
If the initializer could take type parameters it would be ambiguous with the class parameters, if any. Not that this couldn't be worked about in the language specification... but it is a more complex case at the very least. There might also be Java interoperability issues.
Imagine:
class Foo[T](x: T) {
def this[X](z: X) = ...
}
new Foo[Int](42) // T is Int? X is ...? Or ...?
Personally I wish Scala followed an Eiffel-like pattern (only named constructors or "factory methods"), but alas, that would not be Scala.
Happy coding.
I am new to C# / OOP and am working on converting an existing application into .net 4.0 framework.
My code is as follows:
Class abc
private IList<string[]> GetReportBatchList()
{
List<string[]> rowList = new List<string[]>();
SqlParameter[] prm = { new SqlParameter("#rpt_doc_type_id", SqlDbType.Int, 9) };
prm[0].Value = 101;
try
{
.....
.....
.....
}
return rowList;
}
class xyz
using abc;
Private Function GenerateReport()
Try
{
Dim rptBatchList As ??????
rptBatchList = GetReportBatchList()
While rptBatchList.Read()
......
......
......
}
catch
{
......
}
What type should rptBatchList be declared as?
Since the return value of GetReportBatchList() has IList of string as its type, it makes sense that rptBatchList should be the same type.
Your second example is VB, but you say you are using C#, so...
For C# it would be IList<string[]>.
My VB is a little rusty, but I think it would be IList(Of String()).
Hmmm... is this a question about correct return types, or a question about translating C# into VB.Net?
According to the function definition you have, rptBatchList will be of type IList<string[]> - obviously declared in the correct syntax for VB.Net.
Further to that, because it is a list of string arrays, it doesn't have a Read() function, so maybe you were looking for something that derives from DbDataReader instead (like a SqlDataReader)? If you do intend to stick with the current definition then you can use either a foreach or a for loop to iterate over the list elements, or you can use Linq extensions and use something like this:
rptBatchList.ForEach(z => { z.ForEach(x => doSomethingWithThisResultString(x)); } );
although that can get messy fast - you probably want to just stick with a couple of nested foreach loops.