因此,定义了TypeScript中的索引签名:
字典
[key: string]: T
Run Code Online (Sandbox Code Playgroud)
排列
[index: number]: T
Run Code Online (Sandbox Code Playgroud)
这些可以包装成一些简单,可重用的类型:
type DictionaryIndex<T> = {
[key: string]: T
}
type ArrayIndex<T> = {
[index: number]: T
}
Run Code Online (Sandbox Code Playgroud)
现在我想将它们包装成单一类型.我试过这个:
type Index<TKey extends string|number, TValue> = {
[key: TKey]: TValue
}
Run Code Online (Sandbox Code Playgroud)
由于以下错误,这不会编译:
索引签名参数必须是"string"或"number"类型.
这不可能吗?
到底是为了什么?
因为
foo(obj: Index<string, Bar>)
foo(obj: Index<string, Bar> & Fooable<string>)
Run Code Online (Sandbox Code Playgroud)
看起来比
foo(obj: { [key: string]: Bar })
foo(obj: { [key: string]: Bar, canFoo: (foo: string) => Bar })
Run Code Online (Sandbox Code Playgroud) 我工作的一个小项目有一些不同类型的数组(例如double[],float[],int[].为了验证/测试/神智的目的,我打印出一些阵列控制台,因为我走.所以我有多种功能看起来如下所示(本例简化 - 假设我只处理单维数组):
void Print(float[] a) // prints an array of floats
{
for (int i = 0; i < a.Length; i++)
{
Console.Write(a[i]);
}
}
void Print(double[] a) // prints an array of doubles
{
for (int i = 0; i < a.Length; i++)
{
Console.Write(a[i]);
}
}
Run Code Online (Sandbox Code Playgroud)
我以无限的智慧认为,通过简单地创建这些函数的通用版本,我可以减少一些代码重复.所以我尝试了这个:
void Print<T>(T t) where T : Array
{
for (int i = 0; i < t.Length; i++)
{
Console.Write(t.GetValue(i));
}
}
Run Code Online (Sandbox Code Playgroud)
Intellisense没有抱怨,但编译器失败并出现一个非常有趣的错误:
Constraint cannot …
注意:我最后添加了很多Of interest评论.这些并不是在暗示一个人应该使用inline和static type parameters 威利愿意不愿意,他们有这么一个没有花时间搜索大量的SO与此相关的问题,以更好地理解这些概念的问题.
我知道当需要使函数通用并且需要零(0)值时,F#提供GenericZero.
解析为任何原始数字类型的零值或具有名为Zero的静态成员的任何类型.
所以这让我相信使用GenericZero字符串类型我只需要添加一个名为Zero的静态成员.
由于System.String是.Net框架的一部分,修改.Net源代码不是应该做的.但是,F#提供了Type Extensions.
类型扩展允许您将新成员添加到先前定义的对象类型.
此外,F#提供了String模块,但缺少GenericZero.
有关创建类型扩展的好教程,请参阅:将函数附加到类型.
我测试的代码:
这是在一个名为的项目中 Library1
namespace Extension.Test
module Extensions =
type System.String with
static member Something = "a"
static member StaticProp
with get() = "b"
static member Zero
with get() = "c"
Run Code Online (Sandbox Code Playgroud)
这是在一个名为的项目中 Workspace
namespace Extension.Test
module main =
open Extensions
[<EntryPoint>]
let main argv =
let stringSomething = System.String.Something
printfn …Run Code Online (Sandbox Code Playgroud) generics extension-methods f# type-inference generic-constraints
以下F#代码
let f<'T when 'T: (member Id:int)> (t:'T) = t.Id
不接受以下错误:
错误FS0670此代码不够通用.^ T :(成员get_Id:^ T - > int)时的类型变量^ T无法一般化,因为它会逃避其范围.
怎么了?怎么解决?
编辑
@Fyodor:很棘手!我做了一些测试,发现更多的陌生感:
let inline f1<^T when ^T: (member Id:int)> (t:^T) = ( ^T: (member Id:int) t )
let inline f2<'T when 'T: (member Id:int)> (t:'T) = ( 'T: (member Id:int) t )
let inline f3<'T when 'T: (member Id:int)> (t:'T) = ( ^T: (member Id:int) t )
let inline f4 t = ( ^T: (member Id:int) t )
Run Code Online (Sandbox Code Playgroud)
f1在<^ T中给出错误 …
嗨,我想上课:
class Matrix <T>
where T : // I don't know what to write here
{
T[][] elements;
}
Run Code Online (Sandbox Code Playgroud)
我希望T可以通过+和*运算符进行加法和乘法运算
我遇到了一个重载方法的问题,这些方法具有看似独占的不同约束.这是我的例子:
public class A
{
public void Do<T>() where T : class
{
}
public void Do<T>() where T : struct
{
}
}
Run Code Online (Sandbox Code Playgroud)
并且这不会编译时出现以下错误"已定义相同签名的成员".是否有可能同时满足这两个条件,或者仅仅是C#编译器的限制?
我在使这个通用约束工作时遇到了一些麻烦.
我有两个接口.
我希望能够将ICommandHandlers TResult类型限制为仅使用实现ICommandResult的类型,但ICommandResult有自己需要提供的约束.ICommandResult可能会从其Result属性返回值或引用类型.我错过了一些明显的东西吗 谢谢.
public interface ICommandResult<out TResult>
{
TResult Result { get; }
}
public interface ICommandHandler<in TCommand, TResult> where TCommand : ICommand
where TResult : ICommandResult<????>
{
TResult Execute( TCommand command );
}
Run Code Online (Sandbox Code Playgroud) 我对enum通用约束感兴趣,但是当我在Build上切换项目的语言版本时?高级,我仍然遇到错误« C#5中不可用;即使重新打开项目,也请使用语言版本7.3或更高版本 »。
项目类型是ASP.NET MVC应用程序。
给定一个类型的对象,System.Reflection.MethodInfo如何提取通用参数约束?不知怎的,我找不到有关此的合理信息。
如何指定泛型类型参数只能是协议(或符合该协议的协议),而不能是符合该协议的类?
例如:
import Foundation
@objc protocol MyProtocol {
var name: String { get }
}
@objc protocol MySubProtocol: MyProtocol {
func foo()
}
class MyImplementation: MySubProtocol {
var name: String
init(name: String) {
self.name = name
}
func foo() {
print("Foo! Name: \(self.name)")
}
}
class InterfaceMaker<T: MyProtocol> {
init() {}
func makeInterface() -> NSXPCInterface {
return NSXPCInterface(with: T.self) // Cannot convert value of type 'T.Type' to expected argument type 'Protocol'
}
func getProxy() -> T? {
// Some magic …Run Code Online (Sandbox Code Playgroud) generics ×7
c# ×6
.net ×3
f# ×2
arrays ×1
asp.net-mvc ×1
c#-7.3 ×1
reflection ×1
swift ×1
typescript ×1